我有一张表格,用于记录学生在特定日期的某个科目的分数。表 perf 具有 id、date、student、subject、mark 列。
目标:我想使用单个查询将学生每天获得的分数与特定科目的最高、最低和平均班级分数进行比较,例如:
SELECT date,mark,highest,lowest,avg,student FROM ....
->
2021-09-07,73,82,58,69,2c3
2021-09-09,81,84,62,75,2c3
2021-09-14,78,78,68,73,2c3
2021-09-17,75,89,59,73,2c3
如何通过单一陈述实现我的目标?
我对中间步骤持开放态度,例如创建视图。
我使用的是MySQL 8.0.33。
数据如下:
"id","date","student","subject","mark"
"1","2021-09-6","a1b","English","78"
"2","2021-09-7","a1b","Art","63"
"3","2021-09-8","a1b","Math","67"
"4","2021-09-09","a1b","Art","71"
"5","2021-09-09","a1b","English","74"
"6","2021-09-10","a1b","Math","65"
"7","2021-09-13","a1b","English","81"
"8","2021-09-14","a1b","Art","68"
"9","2021-09-15","a1b","Math","70"
"10","2021-09-16","a1b","English","79"
"11","2021-09-17","a1b","Art","70"
"12","2021-09-17","a1b","Math","68"
"14","2021-09-6","2c3","English","68"
"15","2021-09-7","2c3","Art","73"
"16","2021-09-8","2c3","Math","57"
"17","2021-09-09","2c3","Art","81"
"18","2021-09-09","2c3","English","74"
"19","2021-09-10","2c3","Math","55"
"20","2021-09-13","2c3","English","73"
"21","2021-09-14","2c3","Art","78"
"22","2021-09-15","2c3","Math","60"
"23","2021-09-16","2c3","English","71"
"24","2021-09-17","2c3","Art","75"
"25","2021-09-17","2c3","Math","58"
"26","2021-09-6","3d4","English","53"
"27","2021-09-7","3d4","Art","58"
"28","2021-09-8","3d4","Math","56"
"29","2021-09-09","3d4","Art","62"
"30","2021-09-09","3d4","English","54"
"31","2021-09-10","3d4","Math","51"
"32","2021-09-13","3d4","English","51"
"33","2021-09-14","3d4","Art","68"
"34","2021-09-15","3d4","Math","60"
"35","2021-09-16","3d4","English","58"
"36","2021-09-17","3d4","Art","59"
"37","2021-09-17","3d4","Math","58"
"38","2021-09-6","4ef","English","87"
"39","2021-09-7","4ef","Art","82"
"40","2021-09-8","4ef","Math","91"
"41","2021-09-09","4ef","Art","84"
"42","2021-09-09","4ef","English","79"
"43","2021-09-10","4ef","Math","81"
"44","2021-09-13","4ef","English","73"
"45","2021-09-14","4ef","Art","78"
"46","2021-09-15","4ef","Math","82"
"47","2021-09-16","4ef","English","82"
"48","2021-09-17","4ef","Art","89"
"49","2021-09-17","4ef","Math","92"
我能够使用 GROUP BY 获得最高、最低、平均班级分数,如下所示:
SELECT date,subject,MAX(mark) AS highest, MIN(mark) AS lowest, FORMAT(AVG(mark),0) AS avg FROM perf GROUP BY date,subject
->
2021-09-06,English,87,53,72
2021-09-07,Art,82,58,69
2021-09-08,Math,91,56,68
2021-09-09,Art,84,62,75
2021-09-09,English,79,54,70
2021-09-10,Math,81,51,63
尝试将标记和学生合并到上述查询中会给出毫无意义的结果:
SELECT date,subject,mark,MAX(mark) AS highest, MIN(mark) AS lowest, FORMAT(AVG(mark),0) AS avg,student FROM perf GROUP BY date,subject,mark,student
->
2021-09-16,English,71,71,71,71,2c3
2021-09-07,Art,73,73,73,73,2c3
2021-09-13,English,73,73,73,73,2c3
2021-09-13,English,73,73,73,73,4ef
2021-09-09,English,74,74,74,74,a1b
2021-09-09,English,74,74,74,74,2c3
2021-09-17,Art,75,75,75,75,2c3
2021-09-06,English,78,78,78,78,a1b
我尝试了几件事,但当我指定学生、科目和日期如下时,仅成功地将分数、最高、最低、平均、学生组合在一个结果中,但这太具体了,不是我想要的:
SELECT (SELECT date FROM perf WHERE student='2c3' AND subject='Art' AND date='2021-09-07') AS date,
(SELECT mark FROM perf WHERE student='2c3' AND subject='Art' AND date='2021-09-07') AS mark,
(SELECT MAX(mark) FROM perf WHERE subject='Art' AND date='2021-09-07') AS highest,
(SELECT MIN(mark) FROM perf WHERE subject='Art' AND date='2021-09-07') AS lowest,
(SELECT FORMAT(AVG(mark),0) FROM perf WHERE subject='Art' AND date='2021-09-07') AS avg
->
2021-09-07,73,82,58,69
SQL 在线编译器的工作量证明 GitHub 输入和输出:https://gist.github.com/xentzenith/ccdcc3e11f377195645cf2db8a4dccf0
为了实现将学生获得的分数与每天特定科目的最高、最低和平均班级分数进行比较的目标,您可以结合使用窗口函数和子查询。
WITH stats AS (
SELECT
date,
subject,
MAX(mark) OVER (PARTITION BY date, subject) AS highest,
MIN(mark) OVER (PARTITION BY date, subject) AS lowest,
AVG(mark) OVER (PARTITION BY date, subject) AS avg
FROM perf
)
SELECT
p.date,
p.mark,
s.highest,
s.lowest,
ROUND(s.avg, 0) AS avg,
p.student
FROM perf p
JOIN stats s ON p.date = s.date AND p.subject = s.subject
WHERE p.mark = s.mark;
统计 CTE 使用窗口函数(MAX()、MIN()、AVG())计算每个主题在每个日期的最高分、最低分和平均分。 PARTITION BY 子句指定应用聚合函数的行组。如果您使用适当的 SQL 版本,它应该适合您:)