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

按Varchar字段分组异常:如何获取课程最后一次修读成绩?

解决方法:取最后一次修读的成绩而非最高成绩

你的问题核心在于:MAX(GRADE)是取该课程所有修读记录中的最高成绩,但你实际需要的是最后一次修读(对应最大行号)的成绩——这两个逻辑完全不同,当最后一次修读的成绩不是最高分的时候(比如补考分数更低),就会出现错误结果。

下面提供两种可靠的实现方法:

方法1:使用窗口函数ROW_NUMBER()(推荐)

窗口函数是处理这类“分组取最新/最后一条记录”场景的最优方案,逻辑清晰且性能较好:

WITH RankedCourses AS (
    SELECT 
        NAME, 
        COURSE, 
        HRSCODE, 
        GRADE,
        -- 按学生、课程、HRSCODE分组,组内按行号降序排名,最后一次修读的记录排第1
        ROW_NUMBER() OVER (PARTITION BY NAME, COURSE, HRSCODE ORDER BY ROW_NUM DESC) AS rn
    FROM #TEMP
)
SELECT NAME, COURSE, HRSCODE, GRADE
FROM RankedCourses
WHERE rn = 1; -- 只取每组排名第1的记录(最后一次修读)

说明:

  • PARTITION BY NAME, COURSE, HRSCODE:将相同学生、相同课程、相同HRSCODE的记录划分为一组
  • ORDER BY ROW_NUM DESC:组内按行号从大到小排序,行号最大的记录(最后一次修读)会被标记为rn=1
  • 最后筛选rn=1的记录,就能得到每个课程最后一次修读的成绩

方法2:使用关联子查询

如果你使用的数据库不支持窗口函数(不过现在主流数据库都支持),可以用关联子查询实现:

SELECT t1.NAME, t1.COURSE, t1.HRSCODE, t1.GRADE
FROM #TEMP t1
WHERE t1.ROW_NUM = (
    -- 找到当前学生+课程+HRSCODE对应的最大行号(最后一次修读的行号)
    SELECT MAX(t2.ROW_NUM)
    FROM #TEMP t2
    WHERE t2.NAME = t1.NAME 
      AND t2.COURSE = t1.COURSE 
      AND t2.HRSCODE = t1.HRSCODE
);

说明:

  • 子查询会为每条记录找到同组内的最大行号,外层查询筛选出行号等于这个最大值的记录,也就是最后一次修读的成绩

为什么原来的GROUP BY方法不行?

举个例子:假设Math科目学生第一次修读(行号1)成绩是80,第二次补考(行号2)成绩是70。MAX(GRADE)会返回80,但你需要的是行号2对应的70——这就是原来的查询逻辑不符合需求的根本原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:09:10