为何SELECT MAX(Weight)未达预期?SQL分组查询问题咨询
问题分析与解决办法
一、问题原因
1. GROUP BY + MAX(Weight) 返回全部4行的原因
你大概率是在GROUP BY子句里包含了除ID之外的其他列(比如表中所有列),同时SELECT里也列出了这些列。这种情况下,数据库会把所有列值完全相同的行划分为一个分组,每个分组的MAX(Weight)就是该组自身的Weight值,自然会返回全部4行。正确的分组逻辑应该只按ID聚合,先拿到每个ID对应的最大Weight,再去匹配原表的完整行数据。
2. TOP 1 WITH TIES + ROW_NUMBER() 未成功的原因
ROW_NUMBER()会给每个ID分区内的行按Weight降序分配唯一序号——哪怕两行Weight完全相同,序号也会不同。而TOP 1 WITH TIES只会返回排序后排名为1的行,所以如果某ID下有多个相同最大Weight的行,这种写法只能返回其中一行;如果你的窗口函数没加PARTITION BY ID或者排序方向写反了(比如升序),也会直接导致结果不符合预期。
二、解决办法
方法1:先聚合关联原表
先通过GROUP BY ID获取每个ID的最大Weight,再通过内连接匹配原表的完整数据:
SELECT t1.* FROM Table1 t1 INNER JOIN ( -- 先拿到每个ID的最大Weight SELECT ID, MAX(Weight) AS MaxWeight FROM Table1 GROUP BY ID ) t2 ON t1.ID = t2.ID AND t1.Weight = t2.MaxWeight
方法2:窗口函数正确写法
场景1:每个ID只取一行最大Weight的行(即使有并列,只取任意一行)
用ROW_NUMBER()分区排序后过滤:
SELECT * FROM ( SELECT *, -- 按ID分区,Weight降序排,给每行编序号 ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Weight DESC) AS rn FROM Table1 ) t WHERE rn = 1
场景2:每个ID取所有最大Weight的行(包含并列的行)
用RANK()搭配TOP 1 WITH TIES,或者直接用DENSE_RANK()过滤:
-- 写法1:TOP 1 WITH TIES + RANK() SELECT TOP 1 WITH TIES * FROM Table1 ORDER BY RANK() OVER(PARTITION BY ID ORDER BY Weight DESC) -- 写法2:子查询 + DENSE_RANK() SELECT * FROM ( SELECT *, DENSE_RANK() OVER(PARTITION BY ID ORDER BY Weight DESC) AS rnk FROM Table1 ) t WHERE rnk = 1
内容的提问来源于stack exchange,提问作者Syngltake
相关产品推荐
相关产品推荐

