从值具有间隙的表中检索Starting和Ending值

时间:2017-07-06 06:43:38

标签: sql sql-server tsql

如何从存在TicketType和TicketNo列的表中检索值。每个TicketType都可以包含多个TicketNos,这些TicketNos之间可能存在间隙。 TicketNos不是由系统生成的。不是我的选择。以下是数据和所需输出的示例:

    declare @tickets table ( TicketType varchar(20), 
                         TicketNo int )
insert into @tickets( tickettype, ticketno )
select 'AIRCON 1', 1 
union all 
select 'AIRCON 1', 2 
union all 
select 'AIRCON 1', 3 
union all 
select 'AIRCON 1', 6 
union all 
select 'AIRCON 1', 7 
union all 
select 'AIRCON 1', 8 
union all 
select 'AIRCON 1', 9 
union all 
select 'AIRCON 2', 1 
union all 
select 'AIRCON 2', 2 
union all 
select 'AIRCON 2', 3 
union all 
select 'AIRCON 2', 4 
union all 
select 'AIRCON 2', 5 
union all 
select 'AIRCON 3', 1 
union all 
select 'AIRCON 3', 2 
union all 
select 'AIRCON 3', 9 
union all 
select 'AIRCON 3', 10 

select * from @tickets

SELECT 'AIRCON 1' TicketType, 1 Starting, 3 Ending 
union all
select 'AIRCON 1', 6, 9
union all 
select 'AIRCON 2', 1, 5
union all
select 'AIRCON 3', 1, 2
union all
select 'AIRCON 3', 9, 10

示例数据:

+------------------------------------+
|   TicketType           TicketNo    |
+------------------------------------+
| AIRCON 1             1             |
| AIRCON 1             2             |
| AIRCON 1             3             |
| AIRCON 1             6             |
| AIRCON 1             7             |
| AIRCON 1             8             |
| AIRCON 1             9             |
| AIRCON 2             1             |
| AIRCON 2             2             |
| AIRCON 2             3             |
| AIRCON 2             4             |
| AIRCON 2             5             |
| AIRCON 3             1             |
| AIRCON 3             2             |
| AIRCON 3             9             |
| AIRCON 3             10            |

期望的结果

| TicketType Starting    Ending      |
| ---------- ----------- ----------- |
| AIRCON 1   1           3           |
| AIRCON 1   6           9           |
| AIRCON 2   1           5           |
| AIRCON 3   1           2           |
| AIRCON 3   9           10          |
+------------------------------------+

2 个答案:

答案 0 :(得分:2)

这是岛屿问题的变化。

select TicketType, min(ticketno), max(ticketno)
from (
    select TicketType, ticketno, row_number() over( partition by tickettype order by ticketno) - ticketno grp
    from @tickets
) t
group by TicketType, grp
order by TicketType, min(ticketno)

答案 1 :(得分:0)

您必须计算数据中岛屿的分组列(根)。像这样:

;with cteMain as (
    select
        *
        , lag(t.TicketNo, 1, -1) over (order by t.TicketType, t.TicketNo) as TicketNoLag
    from @tickets t
), cteHierarchy as (
    select
        m.TicketType
        , m.TicketNo
        , m.TicketNoLag
        , m.TicketNo as Root
    from cteMain m
    where m.TicketNo - m.TicketNoLag <> 1
    union all
    select
        m.TicketType
        , m.TicketNo
        , m.TicketNoLag
        , h.Root as Root
    from cteMain m
        inner join cteHierarchy h on m.TicketNoLag = h.TicketNo
            and m.TicketType = h.TicketType
            and m.TicketNo - m.TicketNoLag = 1
)
select
    h.TicketType
    , min(h.TicketNo) as Starting
    , max(h.TicketNo) as Ending
from cteHierarchy h
group by h.TicketType, h.Root
order by h.TicketType