相关文章推荐
道上混的杯子  ·  findstr | Microsoft Learn·  1 年前    · 
害羞的领带  ·  【每日鲜蘑】Unable to ...·  1 年前    · 
老实的香槟  ·  python - Why do I get ...·  1 年前    · 
潇洒的书签  ·  python - Name 'file' ...·  1 年前    · 
平均在岗职工人数 = 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:在分区内进行排序
# Notice:MySQL中大小写不敏感 

测试数据
根据需求及相关公式,基于输入的数据进行同表剩余字段的数据自更新,相关代码如下:

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  
      --由于年份和月份也需经过函数进行更新,取YEAR (dt)、MONTH (dt)而非直接取用字段year、month(此时字段值为空),同理AVG(((employee_begin + employee_end)/2))
			labour_productivity ) b --将查询出的结果存储到临时表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的我来说十分有帮助。在您的博客中,我了解到了如何用左连接去除重复行,这对于我来说是一种很新颖的方法。除此之外,我还想分享一些和该博文相关的知识和技能,比如索引的使用、分组和聚合函数等。希望您能够继续分享您的经验和技巧,让我们一起进步! 如何写出更高质量的博客,请看该博主的分享:https://blog.csdn.net/lmy_520/article/details/128686434?utm_source=csdn_ai_ada_blog_reply2 如果您持续创作,完成第三篇博客,并且质量分达到 80 分以上,在评论区就有机会获得红包奖励哦! MySQL记录2.0-表连接去重(以左连接为例) 2301_78544639: 有点不错哦 Mysql记录-移动平均 CSDN-Ada助手: MySQL入门 技能树或许可以帮到你:https://edu.csdn.net/skill/mysql?utm_source=AI_act_mysql