我已经看了这里的其他几个问题/答案,但我无法将它们应用于我的问题。我正试图根据一个关键列来识别多个连续中断。我发现的大多数例子都不处理同一个键列的序列中的多个中断。
Sample data:
Location Number
------------------------
300 15
300 16
300 17
300 18
300 21
300 22
300 23
400 10
400 11
400 14
400 16
Here is the result I am looking for:
Location StartNumber StartNumber
------------------------------------------
300 15 18
300 21 23
400 10 11
400 14 14
400 16 16
这是一个相对可移植的SQL解决方案,因为您没有指定DB
Create Table SampleData (Location int, Number Int)
INSERT INTO SampleData VALUES (300, 15)
INSERT INTO SampleData VALUES (300, 16)
INSERT INTO SampleData VALUES (300, 17)
INSERT INTO SampleData VALUES (300, 18)
INSERT INTO SampleData VALUES (300, 21)
INSERT INTO SampleData VALUES (300, 22)
INSERT INTO SampleData VALUES (300, 23)
INSERT INTO SampleData VALUES (400, 10)
INSERT INTO SampleData VALUES (400, 11)
INSERT INTO SampleData VALUES (400, 14)
INSERT INTO SampleData VALUES (400, 16)
SELECT
t1.Location,
t1.Number AS startofgroup,
MIN(t2.Number) AS endofgroup
FROM (SELECT Number , Location
FROM SampleData tbl1
WHERE NOT EXISTS(SELECT *
FROM SampleData tbl2
WHERE tbl1.Number - tbl2.Number = 1
and tbl1.Location = tbl2.Location)) t1
INNER JOIN (SELECT Number , Location
FROM SampleData tbl1
WHERE NOT EXISTS(SELECT *
FROM SampleData tbl2
WHERE tbl2.Number - tbl1.Number = 1
and tbl1.Location = tbl2.Location)) t2
ON t1.Number <= t2.Number
and t1.Location = t2.Location
GROUP BY
t1.Location,
t1.Number
ORDER BY
Location,
startofgroup
输出
Location startofgroup endofgroup
----------- ------------ -----------
300 15 18
300 21 23
400 10 11
400 14 14
400 16 16
它是清单2的修改版本。用于识别岛屿的基于集合的解决方案。亚历山大·科扎克的《从岛屿和序列数的差距》
如果您正在寻找SQL Server 2005及更高版本的更多选项,您应该搜索短语"Itzik Ben Gan gaps and islands"
如果您使用的是支持lag()函数的RDBMS,那么它应该会告诉您中断的位置。然后,您应该能够使用它,以及一些case语句和小心使用min()和max()函数,来获得您想要的查询。
select location, lag_number as startnumber, number as endnumber
from(select location, number, lag_number
from(
select location, number
, lag(number) over (partition by location order by number) as lag_number
from table
)a
where number is not null and lag_number is not null
)b
where number-lag_number>1 order by 1,2,3;