订阅更新

每个学生的最高成绩:并列取课程号最小的

SQL 实战 123 题 · 第 61 题 中等 约 2 分钟读完

LeetCode 1112 · 分组取首行、多字段排序

本文目录
  1. 面试怎么回答
  2. 题意
  3. 表结构
  4. 思路
  5. 参考解法
  6. 易错点

面试怎么回答

ROW_NUMBER() OVER (PARTITION BY student_id ORDER BY grade DESC, course_id) 取 rn = 1,第二排序键 course_id 解决并列,外层再 ORDER BY student_id。并列规则写进排序键,结果才是确定的。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

题意

选课表记录学生、课程和成绩。找出每个学生成绩最高的一门课和成绩;成绩并列时取课程号最小的那门;结果按学生 ID 升序。

表结构

  • Enrollments:student_id、course_id、grade;(student_id, course_id) 为主键

思路

按学生分区,先按成绩降序、再按课程号升序排,取第一行。因为排序键已经能唯一确定一行,用 ROW_NUMBER 更贴切。原解法漏了题目要求的「按学生 ID 排序」。

参考解法

select student_id,course_id ,grade
from (
select student_id,course_id ,grade,
rank()over(partition by student_id order by grade desc,course_id) rK
from Enrollments
)t1
where rk =1

另一种写法:ROW_NUMBER + 外层排序

SELECT student_id, course_id, grade
FROM (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY student_id ORDER BY grade DESC, course_id) AS rn
  FROM Enrollments
) t
WHERE rn = 1
ORDER BY student_id

易错点

  • 只按成绩排序时并列结果不确定,必须加上 course_id 作为第二排序键。
  • 别忘了外层 ORDER BY student_id。
刷题进度保存在当前浏览器