MySQL:在不返回最高值的窗口函数中使用 MAX

Posted

技术标签:

【中文标题】MySQL:在不返回最高值的窗口函数中使用 MAX【英文标题】:MySQL: Using MAX in a window function not returning highest values 【发布时间】:2021-08-25 21:00:21 【问题描述】:

我正在寻找每个 student_id 的最高成绩。 成绩分数保存在此表中:

招生表:

student_id course_id grade
2 2 95
2 3 95
1 1 90
1 2 99
3 1 80
3 2 75
3 3 82

正确的结果应该是:

student_id course_id grade
1 2 99
2 2 95
3 3 82

这是我正在尝试的查询:

SELECT student_id, course_id, grade
 FROM Enrollments
 GROUP BY student_id
 HAVING grade = (SELECT MAX(grade) OVER(PARTITION BY student_id))
 ORDER BY student_id ASC    

但是通过这个查询,我得到的结果是:

student_id course_id grade
1 2 90
2 2 95
3 3 80

即学生1的成绩是90,什么时候应该是99,学生2的成绩是80,什么时候应该是82。

问题似乎是这个查询只是从表中的第一个 course_id 中选择最高成绩,但我不确定为什么会这样。

【问题讨论】:

【参考方案1】:

请试试这个查询。

SELECT e.student_id, e.course_id, e.grade
FROM Enrollments e INNER JOIN 
(SELECT student_id as student_id, MAX(grade) as grade FROM Enrollments GROUP BY student_id) sbq 
ON e.student_id = sbq.student_id
WHERE e.grade = sbq.grade;

【讨论】:

只是好奇 - 为什么 WHERE 而不是 AND @Strawberry 通常建议在 Join 条件中仅使用 Unique key 列,而在 WHERE 中使用其他键列。这里 student_id 不是唯一的,而是身份列,而成绩是事实。虽然在这个特殊的情况下,它也可以与 AND 一起工作。 不,这不是规则。【参考方案2】:

您可以使用 row_number 来获得所需的结果

CREATE TABLE Table1
    (`student_id` int, `course_id` int, `grade` int)
;
INSERT INTO Table1
    (`student_id`, `course_id`, `grade`)
VALUES
    (2, 2, 95),
    (2, 3, 95),
    (1, 1, 90),
    (1, 2, 99),
    (3, 1, 80),
    (3, 2, 75),
    (3, 3, 82)
;
SELECT `student_id`, `course_id`, `grade`
FROM (SELECT `student_id`, `course_id`, `grade`
, ROW_NUMBER() OVER(PARTITION BY `student_id` ORDER BY `grade` DESC) rn
FROM Table1) t1
WHERE rn= 1
学生ID | course_id |年级 ---------: | --------: | ----: 1 | 2 | 99 2 | 2 | 95 3 | 3 | 82

db小提琴here

【讨论】:

感谢您的回答。您是否对为什么窗口函数没有按照我尝试的方式工作(使用 MAX())有任何见解?我试图弄清楚我对逻辑的误解。谢谢! 一个窗口函数,就像我的例子一样,逐行工作,这就是为什么你有一个 CTE 或一个外部 SELECT 。您的问题是您的查询在 dbfiddle 中无法正常工作,而进一步的问题是您必须记住结果集是 unordered 这就是为什么您需要像其他答案或类似的结构就我而言,我用 row_number 下订单

以上是关于MySQL:在不返回最高值的窗口函数中使用 MAX的主要内容,如果未能解决你的问题,请参考以下文章

MySQL: GROUP BY + HAVING MAX(...) --- 为啥 HAVING MAX(grade) 不会返回最高等级?

如何在不使用存储过程的情况下在表函数中返回值 exec?

求一个程序,要求是: 设计一个函数,以字符串为参数,返回该字符串中出现频率最高的字符。

SQL 窗口函数 - 自上次 Max 以来的行数

使用基于 Avg 的 Max 和 Min 来确定最低平均成本和最高平均成本时出错(MySQL)

如何在不使用 c# 中的内置函数的情况下获得投球手的最低和最高分数