You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需排名函数,查询各科目最高分学生的SQL语句优化问询

问题背景

已知三张表结构:

  • Student (StudentID int, StudentName varchar(20))
  • Subject (SubjectID int, SubjectName varchar(20))
  • Score (ScoreID int, StudentID int, SubjectID int, Score int)

样本数据如下:

-- 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
    )

优化点说明
  1. 去掉冗余的JOIN和嵌套:原SQL在计算科目最高分的子查询里,没必要把Score和Subject关联——分组求最高分只用到Score表的SubjectID和Score字段,这一步完全是多余的。优化后的语句直接在主查询里关联Subject拿科目名称,层级从3层降到1层嵌套,结构清晰多了。
  2. 语义更直观:NOT EXISTS的逻辑非常直白:“当前这条分数记录,在同一个科目里找不到比它更高的分数”,完美对应“该科目最高分”的需求,读代码的时候一眼就能懂,后续维护也方便。
  3. 性能更优:如果你的Score表在SubjectID和Score字段上建了索引,NOT EXISTS的子查询可以直接利用索引快速过滤,相比原方案的多次JOIN,执行效率会更高。
  4. 兼容同分场景:如果某个科目有多个学生分数相同且都是最高分,这个查询会返回所有符合条件的学生,和你原SQL的行为保持一致,不会遗漏数据。

内容的提问来源于stack exchange,提问作者Anshul Dahiya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:34:34