使用子查询解决MySQL分组结果的平局问题
解决MySQL查询每个学生最高分数对应课程的问题
我来帮你搞定这个查询需求~首先明确一下我们要实现的核心目标:
- 找出每个学生的
student_id、对应的课程course_id,以及该学生的最高分数marks - 如果同一个学生有多门课程分数都是最高分,只保留
course_id最小的那一行 - 最终结果按
student_id升序排列
方法一:使用窗口函数(MySQL 8.0+推荐)
窗口函数是处理这类分组排名问题最直观的方式,用ROW_NUMBER()可以轻松给每个学生的成绩排序:
SELECT student_id, course_id, marks FROM ( SELECT student_id, course_id, marks, -- 按学生分组,先按分数降序排序,分数相同则按course_id升序排序并编号 ROW_NUMBER() OVER ( PARTITION BY student_id ORDER BY marks DESC, course_id ASC ) AS rn FROM signed_up ) AS ranked_data -- 只取每个学生编号为1的行(即最高分且course_id最小的行) WHERE rn = 1 ORDER BY student_id ASC;
这个逻辑非常清晰:
- 内层查询给每个学生的所有成绩行编号,最高分的行排第1;分数相同时,
course_id更小的行排第1 - 外层查询筛选出编号为1的行,就是我们要的目标结果
方法二:子查询关联(兼容老版本MySQL)
如果你的MySQL版本低于8.0,不支持窗口函数,可以用子查询+分组的方式实现:
SELECT su.student_id, MIN(su.course_id) AS course_id, su.marks FROM signed_up su -- 先关联子查询,找到每个学生的最高分数 INNER JOIN ( SELECT student_id, MAX(marks) AS max_marks FROM signed_up GROUP BY student_id ) AS student_max_marks ON su.student_id = student_max_marks.student_id AND su.marks = student_max_marks.max_marks -- 对每个学生的最高分课程,取最小的course_id GROUP BY su.student_id, su.marks ORDER BY su.student_id ASC;
步骤拆解:
- 子查询先算出每个学生的最高分数
- 关联原表,筛选出所有学生分数等于其最高分的行
- 按学生和分数分组,取分组内最小的
course_id
你原来的SQL问题所在
你之前尝试的写法里,子查询select min(course_id)没有和外层的student_id做关联,导致拿到的是全局范围内最小的course_id,而不是当前学生最高分对应的最小course_id,所以结果不符合预期。
内容的提问来源于stack exchange,提问作者anon_swe
相关产品推荐
相关产品推荐

