n
∑
i
=
1
n
第
i
月平均人数
.
月平均人数=(月初人数+月末人数)/2
;
n:报告期月份数
劳动生产率单位:/人•年
要求:
仅输入产量和月初月末在岗职工人数,其余字段自动计算。
备注:
平均在岗职工人数从当年度1月开始计算,按报告期进行计算填报。
通过分析上述需求,构建对应劳动生产率表格时包含如下字段:
字段名
|
类型
|
描述
|
year
|
int
|
年份
|
month
|
int
|
月份
|
dt
|
date
|
统计时间
|
output
|
double
|
产量
|
employee_begin
|
int
|
月初职工人数
|
employee_end
|
int
|
月末职工人数
|
employee_month_average
|
int
|
月平均人数
|
employee_average
|
int
|
平均人数
|
labour_productivity
|
double
|
劳动生产率
|
相关建表语句如下:
CREATE TABLE labour_productivity (
year INT NULL COMMENT '年份',
month INT NULL COMMENT '月份',
dt date NULL COMMENT '统计时间',
output DOUBLE NULL COMMENT '产量',
employee_begin INT NULL COMMENT '月初职工人数',
employee_end INT NULL COMMENT '月末职工人数',
employee_month_average INT NULL COMMENT '月平均人数',
employee_average INT NULL COMMENT '平均人数',
abour_productivity DOUBLE NULL COMMENT '劳动生产率'
需求分解:月平均人数(employee_month_average )在mysql8.0中可通过计算列的设置达到自动计算的需求;平均人数(employee_average)需要对月平均人数列进行滚动求均值。
值得注意的是:
- 产量数据也应是累计量,如3月的产量是第1、2、3月的产量和;
- 在计算劳动生产率时,要基于年份进行分区
在此次项目中,难点在于平均人数(employee_average)需对月平均人数字段需对月平均人数(employee_month_average )在同一年中进行移动平均。在mysql中可使用开窗函数完成移动计算,函数的基本语法如下:
开窗函数() OVER(partition by 字段名 order by字段名)
- partition by:需分区的字段(可选择不使用,本问题中需使用)
- order by:在分区内进行排序
根据需求及相关公式,基于输入的数据进行同表剩余字段的数据自更新,相关代码如下:
UPDATE labour_productivity labour
SET `year` = YEAR (dt),
`month` = MONTH (dt),
employee_month_average =(employee_begin + employee_end)/2,
employee_average =(SELECT
b.avg1
(SELECT
AVG(((employee_begin + employee_end )/2)) over (PARTITION BY YEAR ( dt ) ORDER BY MONTH ( dt )) AS avg1
labour_productivity ) b
WHERE
b.dt = labour.dt ),
Labour_productivity = ROUND(output/employee_average,2);
结果如下:
代码注解:
- mysql根据表数据来更新自身(同表自更新问题)
在上述代码中年份(year)、月份(month)、月平均人数字段(employee_month_average )可直接使用YEAR、MONTH函数和表达式进行更新,而平均人数(employee_average)需从本表中进行查询并计算再进行更新。当直接将查询结果set到employee_average字段中时将会报如下错误:
You can’t specify target table for update in FROM clause
报错意思为:不能将同一表中查询的数据作为同一表的更新数据
解决方法: 借助一个虚拟的中间表,将要查询计算出的移动均值赋值给employee_average。即:在select外边套一层,让数据库认为不是从同一张表的数据查询出的结果进行自更新。
UPDATE labour_productivity labour
SET employee_average =(SELECT
b.avg1
(SELECT
AVG(((employee_begin + employee_end)/2)) over (PARTITION BY YEAR (dt) ORDER BY MONTH (dt)) AS avg1
labour_productivity ) b
WHERE
b.dt = labour.dt );
- 聚合开窗函数
MySQL允许将所有聚合函数用作开窗函数:max()、min() 、sum() 、avg() …
SQL进阶-开窗函数() over(partition by)
sum() over(partition by order by row between … )
MySQL 报错 You can‘t specify target table for update in FROM clause解决办法
mysql 中将表中某一字段值查询出来,更新到另一个字段上的SQL写法
记录一个sql:mysql表根据自身数据来更新自身
在岗职工人均劳动生产率产量平均在岗职工人数在岗职工人均劳动生产率=\frac{产量}{平均在岗职工人数}.在岗职工人均劳动生产率平均在岗职工人数产量其中:平均在岗职工人数∑i1n第i月平均人数n平均在岗职工人数=\frac{\sum_{i=1}^{n}第i月平均人数}{n}.平均在岗职工人数n∑i1n第i月平均人数月平均人数=(月初人数+月末人数)/2;n:报告期月份数劳动生产率单位:/人•年仅输入产量和月初月末在岗职工人数,其余字段自动计算。
CSDN-Ada助手:
MySQL记录2.0-表连接去重(以左连接为例)
2301_78544639:
Mysql记录-移动平均
CSDN-Ada助手: