无需排名函数,查询各科目最高分学生的SQL语句优化问询
问题背景
已知三张表结构:
Student(StudentIDint,StudentNamevarchar(20))Subject(SubjectIDint,SubjectNamevarchar(20))Score(ScoreIDint,StudentIDint,SubjectIDint,Scoreint)
样本数据如下:
-- Student表 StudentID | StudentName ----------|------------ 1 | John 2 | Nash 3 | Albert -- Subject表 SubjectID | SubjectName ----------|------------ 1 | Maths 2 | Physics 3 | Chemistry 4 | English -- Score表 ScoreID | StudentID | SubjectID | Score --------|-----------|-----------|------ 1 | 1 | 1 | 34 2 | 1 | 2 | 45 3 | 1 | 3 | 56 4 | 2 | 1 | 78 5 | 2 | 3 | 23 6 | 2 | 4 | 44 7 | 3 | 1 | 45 8 | 3 | 2 | 10 9 | 3 | 3 | 54 10 | 3 | 4 | 74
需求:编写SQL获取每个科目的最高分学生、分数及科目名称,禁止使用Row_Number()、Rank()、Dense_Rank()函数。
你当前的SQL语句:
select st.StudentName, Score, B.SubjectID from ( select StudentID, Sc.SubjectID, Sc.Score from ( select SubjectID, MAX(Score) as 'Score' from Score Sc inner join subject sb on sc.subjectid = sb.subjectid group by SubjectID ) A inner join score sc on sc.SubjectID = a.SubjectID and sc.Score = A.Score ) B inner join Student st on st.studentID = B.StudentID
优化方案
这里给你一个更简洁高效的写法,同时保留原逻辑的正确性:
SELECT st.StudentName, sc.Score, sb.SubjectName FROM Score sc INNER JOIN Student st ON sc.StudentID = st.StudentID INNER JOIN Subject sb ON sc.SubjectID = sb.SubjectID WHERE NOT EXISTS ( SELECT 1 FROM Score sc2 WHERE sc2.SubjectID = sc.SubjectID AND sc2.Score > sc.Score )
优化点说明
- 去掉冗余的JOIN和嵌套:原SQL在计算科目最高分的子查询里,没必要把
Score和Subject关联——分组求最高分只用到Score表的SubjectID和Score字段,这一步完全是多余的。优化后的语句直接在主查询里关联Subject拿科目名称,层级从3层降到1层嵌套,结构清晰多了。 - 语义更直观:
NOT EXISTS的逻辑非常直白:“当前这条分数记录,在同一个科目里找不到比它更高的分数”,完美对应“该科目最高分”的需求,读代码的时候一眼就能懂,后续维护也方便。 - 性能更优:如果你的
Score表在SubjectID和Score字段上建了索引,NOT EXISTS的子查询可以直接利用索引快速过滤,相比原方案的多次JOIN,执行效率会更高。 - 兼容同分场景:如果某个科目有多个学生分数相同且都是最高分,这个查询会返回所有符合条件的学生,和你原SQL的行为保持一致,不会遗漏数据。
内容的提问来源于stack exchange,提问作者Anshul Dahiya
相关产品推荐
相关产品推荐

