问题描述
|
我之前曾问过类似的问题,但是这种相似性是肤浅的,问题出在更深的地方……
因此,请考虑以下MS sql Server 2008表:
ID | X | Y
------+-------+-------
1 | 1 | 1
2 | 1 | 2
3 | 1 | 2
4 | 1 | 3
5 | 1 | 3
6 | 2 | 4
7 | 2 | 5
8 | 2 | 5
9 | 2 | 5
10 | 3 | 1
11 | 3 | 10
12 | 3 | 10
我需要接收以下结果之一(这到底是什么并不重要):
ID | X | Y
------+-------+-------
4 | 1 | 3
7 | 2 | 5
11 | 3 | 10
要么
ID | X | Y
------+-------+-------
!! 5 | 1 | 3
7 | 2 | 5
11 | 3 | 10
要么
.....
要么
ID | X | Y
------+-------+-------
5 | 1 | 3
9 | 2 | 5
12 | 3 | 10
我需要
X分组表
选择最大Y
选择最大Y的ID
结果也应按X分组
不应出现以下结果:
ID | X | Y
------+-------+-------
4 | 1 | 3
5 | 1 | 3
7 | 2 | 5
8 | 2 | 5
9 | 2 | 5
11 | 3 | 10
12 | 3 | 10
解决方法
DECLARE @Data TABLE (ID INTEGER,X INTEGER,Y INTEGER)
INSERT @Data VALUES (1,1,1),(2,2),(3,(4,3),(5,(6,2,4),(7,5),(8,(9,(10,3,(11,10),(12,10)
;WITH CTE AS
(
SELECT ID,X,Y,ROW_NUMBER() OVER(PARTITION BY X ORDER BY Y DESC,ID ASC) AS RowNo
FROM @Data
)
SELECT ID,Y FROM CTE WHERE RowNo = 1
因此,使用ROW_NUMBER()为每一行分配一个递增的数字,对于每个新的X值,该数字将重置为1。对于X值相同的行,行号由Y降序和ID升序递增分配-因此,对于特定的X值,行号1将分配给具有最高Y值和最低ID值的行。然后,我们添加一个限制,以仅返回RowNo为1的那些。
, 这将为x,y的每个重复组合带来第一行
SELECT t1.*
FROM tablename t1
INNER JOIN
(SELECT MIN(id) id FROM tablename GROUP BY X,Y HAVING COUNT(*)>1)
t2 ON t1.id = t2.id
测试代码得到以下结果:
ID X Y
2 1 2
4 1 3
7 2 5
11 3 10
, 对于此类任务,还有一个更优雅的解决方案:
DECLARE @Data TABLE (ID INTEGER,Y INTEGER);
INSERT @Data VALUES (1,1);
INSERT @Data VALUES (2,2);
INSERT @Data VALUES (3,2);
INSERT @Data VALUES (4,3);
INSERT @Data VALUES (5,3);
INSERT @Data VALUES (6,4);
INSERT @Data VALUES (7,5);
INSERT @Data VALUES (8,5);
INSERT @Data VALUES (9,5);
INSERT @Data VALUES (10,1);
INSERT @Data VALUES (11,10);
INSERT @Data VALUES (12,10);
SELECT TOP 1 WITH TIES
ID,Y
FROM @Data
ORDER BY ROW_NUMBER() OVER(PARTITION BY X ORDER BY Y DESC,ID ASC);