如何在SQL Server中合并连续的间隔

时间:2015-10-24 22:18:58

标签: sql-server

我试图找到合并/组合类别定义的连续区间的有效方法。例如,从此源表:

TYPE   START    END    CATEGORY
----   -----    ----   --------
X         0        5      A
X         5       10      B
X        10       15      B
X        15       20      C
X        20       25      C
Y         0        6      A
Y         6       12      A
Y        12       20      B
Y        20       22      B
Y        24       27      B
Y        27       30      B
Y        35       40      C

查询输出应为:

TYPE   START    END    CATEGORY
----   -----    ----   --------
X         0        5      A
X         5       15      B
X        15       25      C
Y         0       12      A
Y        12       22      B
Y        24       30      B
Y        35       40      C

请注意,对于类型Y,在22和24之间存在差距,因此需要新的组合间隔。

使用SQL Server 2008R2。数据量在数千条记录中,因此不会太大。

感觉这是递归CTE的工作,但我在绕着它缠绕时遇到了麻烦。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:3)

这通常被称为“差距和岛屿”问题。这是我的抨击:

with cte as (
    select * from (values
        ('X',         0,        5,      'A'),
        ('X',         5,       10,      'B'),
        ('X',        10,       15,      'B'),
        ('X',        15,       20,      'C'),
        ('X',        20,       25,      'C'),
        ('Y',         0,        6,      'A'),
        ('Y',         6,       12,      'A'),
        ('Y',        12,       20,      'B'),
        ('Y',        20,       22,      'B'),
        ('Y',        24,       27,      'B'),
        ('Y',        27,       30,      'B'),
        ('Y',        35,       40,      'C')
    ) as x( [Type], [Start], [End], [Category] )
), with_grp as (
    select *, n.Number - dense_rank() over (partition by [Type], [Category] order by n.Number ) as grp
    from cte
    join dbadmin.dbo.Numbers as n
        on n.Number >= cte.Start
        and n.Number <= cte.[End]
)
select [Type], [Category], min([Start]), max([End])
from with_grp
group by [Type], [Category], [grp]
order by [Type], [Category], min([Start])

其中dbadmin.dbo.Numbers是一个计数表(一个表有一列,行是数字1-(一些大数字))。要发现魔法,请从with_grp cte进行原始选择。但是应该这样做。