我有一个包含以下定义的表
CREATE TABLE mytable
(
id INT IDENTITY(1, 1) PRIMARY KEY,
number BIGINT,
status INT
)
和示例数据
INSERT INTO mytable
VALUES (100,0),
(101,0),
(102,0),
(103,0),
(104,1),
(105,1),
(106,0),
(107,0),
(1014,0),
(1015,0),
(1016,1),
(1017,0)
仅查看status = 0
的行,如何将Number
值折叠为连续序列号的范围并找到每个范围的开头和结尾?
即。对于示例数据,结果将是
FROM to
Number 100 103
Number 106 107
Number 1014 1015
Number 1017 1017
答案 0 :(得分:25)
正如评论中所提到的,这是一个典型的差距和岛屿问题。
Itzik Ben Gan推广的解决方案是使用ROW_NUMBER() OVER (ORDER BY number) - number
在“岛屿”内保持不变并且不能出现在多个岛屿中的事实。
WITH T
AS (SELECT ROW_NUMBER() OVER (ORDER BY number) - number AS Grp,
number
FROM mytable
WHERE status = 0)
SELECT MIN(number) AS [From],
MAX(number) AS [To]
FROM T
GROUP BY Grp
ORDER BY MIN(number)
注意:如果number
不能保证是唯一的,请在上面的代码中将ROW_NUMBER
替换为DENSE_RANK
。