如何用SQL计算报表中多列字段的平均值?(含空值处理)
|
admin
2025年3月25日 9:26
本文热度 516
|
不同于之前的AVG函数的使用(只对单列求平均值),今天的分享是如何用SQL计算报表中多列字段的平均值。
假设某在线教育平台需要统计学生的平均成绩,但存在以下复杂情况:学生可能缺考某些科目(成绩为空),不同学生参加考试的科目数量不同。问题:求每个学生的平均分数,其中平均分数 = 总分/实际参加考试科目数,而非固定除以总科目数。案例报表如下,建表语句见文末: 假如每个列都没有空值的话,那么上面报表中5列的平均值等于(math_score+chinese_score+english_score+physics_score+chemistry_score)/5,那要统计每行非空列的数量就不是固定的5列了。要解决上面的问题,就需要统计一下三个指标数量: SQL如下: SELECT student_name, (COALESCE(math_score, 0) + COALESCE(chinese_score, 0) + COALESCE(english_score, 0) + COALESCE(physics_score, 0) + COALESCE(chemistry_score, 0)) AS total_score,
(CASE WHEN math_score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN chinese_score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN english_score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN physics_score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN chemistry_score IS NOT NULL THEN 1 ELSE 0 END) AS valid_columns,
CASE WHEN (CASE WHEN math_score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN chinese_score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN english_score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN physics_score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN chemistry_score IS NOT NULL THEN 1 ELSE 0 END) = 0 THEN NULL ELSE (COALESCE(math_score, 0) + COALESCE(chinese_score, 0) + COALESCE(english_score, 0) + COALESCE(physics_score, 0) + COALESCE(chemistry_score, 0)) / (CASE WHEN math_score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN chinese_score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN english_score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN physics_score IS NOT NULL THEN 1 ELSE 0 END + CASE WHEN chemistry_score IS NOT NULL THEN 1 ELSE 0 END) END AS avg_score FROM data_learning.student_scores;

大多数数据库支持CASE表达式和COALESCE函数,所以基本上可以选择上述的SQL代码来解决问题。 部分数据库支持IF、NULLIF函数等,也可以用这些函数来简化上述代码。SELECT student_name, (COALESCE(math_score, 0) + COALESCE(chinese_score, 0) + COALESCE(english_score, 0) + COALESCE(physics_score, 0) + COALESCE(chemistry_score, 0)) AS total_score,
(IF(math_score IS NOT NULL , 1 , 0 ) + IF(chinese_score IS NOT NULL , 1 , 0 ) + IF(english_score IS NOT NULL , 1 , 0 ) + IF(physics_score IS NOT NULL , 1 , 0 ) + IF(chemistry_score IS NOT NULL , 1 , 0 )) AS valid_columns,
CASE WHEN (IF(math_score IS NOT NULL , 1 , 0 ) + IF(chinese_score IS NOT NULL , 1 , 0 ) + IF(english_score IS NOT NULL , 1 , 0 ) + IF(physics_score IS NOT NULL , 1 , 0 ) + IF(chemistry_score IS NOT NULL , 1 , 0 )) = 0 THEN NULL ELSE (COALESCE(math_score, 0) + COALESCE(chinese_score, 0) + COALESCE(english_score, 0) + COALESCE(physics_score, 0) + COALESCE(chemistry_score, 0)) / (IF(math_score IS NOT NULL , 1 , 0 ) + IF(chinese_score IS NOT NULL , 1 , 0 ) + IF(english_score IS NOT NULL , 1 , 0 ) + IF(physics_score IS NOT NULL , 1 , 0 ) + IF(chemistry_score IS NOT NULL , 1 , 0 ))
END AS avg_score FROM data_learning.student_scores;
create table data_learning.student_scores( student_name varchar(255), math_score INT, chinese_score INT, english_score INT, physics_score INT, chemistry_score INT );
insert into data_learning.student_scores values ('林赛', 90, 85, NULL, 78, 92), ('张三', NULL, NULL, NULL, NULL, NULL), ('李四', 75, 88, 92, 85, 80), ('王五', 80, NULL, 90, 80, 70);
该文章在 2025/3/25 9:47:04 编辑过
|
|