MS SQL查询需求:按Num1与Num2无序分组获取最高Range值的唯一行
解决MS SQL中无序分组并保留原行顺序的问题
我来帮你搞定这个分组查询的问题!你的核心需求是把Num1和Num2视为无序对(比如(1,2)和(2,1)算同一组),然后每组只保留Range值最高的原行,对吧?先说说你原来查询的问题:
原查询的问题分析
你用Concat([Num1], [Num2])作为分组键,这会导致(1,2)变成'12',(2,1)变成'21',被当成两个不同的组,自然会出现重复行;另外用Max([Num1])和Max([Num2])会强制修改原行的数值顺序,不符合你保留原行Num1/Num2的要求。
正确的解决方案:使用窗口函数
我们可以用LEAST()和GREATEST()来生成统一的分组键(不管Num1和Num2的顺序),再结合ROW_NUMBER()窗口函数给每个组内的行按Range降序排序,最后取每组的第一行即可。
WITH RankedRows AS ( SELECT ID, Num1, Num2, Range, -- 按无序组分组,组内按Range降序编号 ROW_NUMBER() OVER ( PARTITION BY LEAST(Num1, Num2), GREATEST(Num1, Num2) ORDER BY Range DESC ) AS rn FROM [dbo].[Range] ) SELECT ID, Num1, Num2, Range FROM RankedRows WHERE rn = 1 ORDER BY Range DESC;
代码解释
LEAST(Num1, Num2)和GREATEST(Num1, Num2):这两个函数会分别取两个数的最小值和最大值,这样(1,2)和(2,1)都会生成(1,2)作为分组依据,确保它们被分到同一组。ROW_NUMBER() OVER(...):给每个组内的行按Range从高到低编号,Range最高的行编号为1。- 最后筛选
rn=1的行,就能得到每组中Range最高的原行,完美保留原表的Num1和Num2顺序。
特殊情况处理
如果同一组内有多个行的Range值相同且都是最高值,ROW_NUMBER()只会随机选其中一行。如果你想保留所有这些行,可以把ROW_NUMBER()换成RANK()或者DENSE_RANK(),这样所有最高Range的行都会被选中。
验证结果
执行上面的查询后,会得到你期望的结果:
| ID | Num1 | Num2 | Range |
|---|---|---|---|
| 9 | 1 | 4 | 3 |
| 4 | 2 | 1 | 2 |
| 5 | 3 | 1 | 1 |
| 6 | 2 | 3 | 1 |
内容的提问来源于stack exchange,提问作者Alexander Raymak
相关产品推荐
相关产品推荐

