如何在GROUP BY分组查询中获取非分组列的最新对应值?
按分组取最新日期对应列值的解决方法
原始数据
| a | b | c | d | e |
|---|---|---|---|---|
| 1 | test | 9 | h | 2024-10-22 08:00:00.000 |
| 1 | test | 9 | l | 2024-10-23 08:00:00.000 |
| 1 | test | 9 | q | 2024-10-22 08:00:00.000 |
预期结果
按a、b、c分组,取每组中e(日期)最新的d值:
| a | b | c | d |
|---|---|---|---|
| 1 | test | 9 | l |
你尝试的方法问题说明
- SQL Server中没有
LAST()聚合函数,直接用GROUP BY搭配LAST(d)的写法不可行:
SELECT a, b, c, last(d) FROM dbo.items GROUP BY a, b, c
LAST_VALUE()窗口函数的写法有误,正确分区应为a,b,c而非d,且窗口函数不能直接在GROUP BY中作为聚合使用:
LAST_VALUE(d) OVER (PARTITION BY d ORDER BY e) AS d
STRING_AGG()可拼接非分组列的值,但不符合取最新值的需求:
STRING_AGG(b, ',') AS b
可行解决方案
方法1:ROW_NUMBER()窗口函数(推荐)
通过窗口函数给每组内的行按日期降序排名,取排名第一的行:
WITH ranked_items AS ( SELECT a, b, c, d, e, -- 按a,b,c分组,每组内按e降序生成排名 ROW_NUMBER() OVER (PARTITION BY a, b, c ORDER BY e DESC) AS rn FROM dbo.items ) SELECT a, b, c, d FROM ranked_items WHERE rn = 1;
注:若同一组存在多个日期相同的最大值,
ROW_NUMBER()会随机返回其中一行;要保留所有最大值行,可替换为RANK()或DENSE_RANK()。
方法2:关联子查询取最大日期
先分组获取每组的最大日期,再关联原表找到对应行:
SELECT i.a, i.b, i.c, i.d FROM dbo.items i INNER JOIN ( -- 先找出每组的最大日期 SELECT a, b, c, MAX(e) AS max_e FROM dbo.items GROUP BY a, b, c ) grouped ON i.a = grouped.a AND i.b = grouped.b AND i.c = grouped.c AND i.e = grouped.max_e;
注:若同一组有多个相同最大日期的行,该方法会返回所有这些行。
方法3:TOP 1 WITH TIES简化写法
利用TOP 1 WITH TIES配合窗口函数,直接返回每组排名第一的行:
SELECT TOP 1 WITH TIES a, b, c, d FROM dbo.items ORDER BY ROW_NUMBER() OVER (PARTITION BY a, b, c ORDER BY e DESC);
内容的提问来源于stack exchange,提问作者Aurelius
相关产品推荐
相关产品推荐

