在SQL Server中合并/扩展具有相同类型的记录

Fra*_*ank 6 t-sql sql-server

我遇到了将相同类型的记录与连续序列合并并从合并记录中计算完整序列的问题.

排序应该在基础ID上完成,因为当序列达到100时序列可能翻转为0.参见输入/输出示例中的最后一项.

是否可以拥有下面列出的输入并具有生成输出的查询,该输出也在下面的SQL Server 2012中列出?

输入

Id     Type     Begin     End
-----------------------------
1      1        10        20
2      1        21        23
3      2        24        28
4      1        29        40
5      2        41        47
6      2        48        50
7      2        75        80
8      1        81        100
9      1        0         10
10     1        11        20
11     1        21        5
12     1        5         6
Run Code Online (Sandbox Code Playgroud)

产量

FromId     ToId     Type     Begin     End    Length
----------------------------------------------------
1          2        1        10        23     13 (23-19)
3          3        2        24        28     4  (28-24)
4          4        1        29        40     11 (40-29)
5          6        2        41        50     9  (50-41)
7          7        2        75        80     5  (80 - 75)
8          12       1        81        20     227*
Run Code Online (Sandbox Code Playgroud)

*(100-81)+ 10 +(100-11 + 20)+(100-21 + 5)+ 1 - > seq的seq

编辑

请注意,源中的第6行和第7行合并,因为它们不是连续的.第6行以50结尾,第7行以75开头.只需要合并具有相同类型的连续行.

Man*_*org 0

这个问题通常可以通过如下的递归来解决:

create table #t ([Id] int, [Type] int, [Begin] int, [End] int);
insert into #t values (1,1,10,20),(2,1,21,23),(3,2,24,28),(4,1,29,40),
(5,2,41,47),(6,2,48,50),(7,2,75,80),(8,1,81,100),(9,1,0,10),(10,1,10,20);

with cRek as (
    -- records with no followup
    select  t.[Type], FromId = t.[Id], ToId = t.[Id], 
            t.[Begin], t.[End], [Length] = t.[End]-t.[Begin]+1
    from    #t t
    left join #t tf
        on  tf.[Type] = t.[Type]
        and tf.[Begin] = (t.[End]+1)%101
        and tf.[Id] > t.[Id]
    where   tf.[Id] is null

    union all

    -- previous record
    select  t.[Type], FromId = t.[Id], ToId = tf.[ToId], 
            t.[Begin], tf.[End], [Length] = tf.[Length]+t.[End]-t.[Begin]+1
    from    #t t
    inner join cRek tf
        on  tf.[Type] = t.[Type]
        and tf.[Begin] = (t.[End]+1)%101
        and tf.[FromId] > t.[Id]
)
select  *
from    cRek r
where   FromId = 
        (select min(x.FromId)
        from    cRek x
        where   x.[Type]=r.[Type] and x.[ToId]=r.[ToId])
order by ToId;

drop table #t;
Run Code Online (Sandbox Code Playgroud)

您的样本有一些小缺陷:

  • 100 后面跟着 0,因此有 101 个不同的元素(模 101!)
  • Id 10 不是 Id 9 的后续元素,因为它们都包含元素 10
  • 从10到23的长度是14,因为它是一个包含区间

HTH,曼弗雷德