SQL组范围值

时间:2011-06-10 15:23:10

标签: sql group-by range gaps-and-islands

我在这里看了几个其他问题/答案,但我不能将它们应用到我的问题中。我试图根据键列识别多个连续中断。我发现的大多数示例都没有处理同一键列的序列中的多个中断。

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

2 个答案:

答案 0 :(得分:2)

这是相对可移植的SQL解决方案,因为您没有指定数据库

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的修改版本。一种用于识别孤岛的基于集合的解决方案。来自Alexander Kozak的Islands and Gaps in Sequential Numbers

如果您正在寻找SQL Server 2005及更高版本的更多选项,则应搜索短语“Itzik Ben-Gan gaps and islands

答案 1 :(得分:0)

好吧,如果您使用的是支持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;