如何将一行合并到 MySQL 中的 GROUP BY 查询中?

问题描述 投票:0回答:1

我有一张表格,用于记录学生在特定日期的某个科目的分数。表 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  
mysql group-by subquery
1个回答
1
投票

Proof of Work

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 版本,它应该适合您:)

© www.soinside.com 2019 - 2024. All rights reserved.