返回间歇日期系列中连续块的第一个和最后一个日期

时间:2014-05-05 04:37:25

标签: sql-server-2008 tsql gaps-and-islands

我正在使用SQL Server 2008 R2并拥有下表。

CREATE TABLE room
(id int, 
 dt date, 
 course char(1), 
 constraint pk_roomtime primary key (id, dt)
);

INSERT INTO room (id, dt, course) values
(1, '20140412', 'A'),
(1, '20140414', 'A'),
(1, '20140415', 'A'),
(1, '20140416', 'B'),
(1, '20140417', 'A'),
(1, '20140421', 'A'),
(1, '20140422', 'B'),
(1, '20140423', 'B');

我必须找到一个房间里每个课程的第一个和最后一个日期,而不考虑日期之间的差距。我对房间1的结果应如下所示:

A    20140412    20140415
B    20140416    20140416
A    20140417    20140421
B    20140422    20140423

我尝试使用联接到日历表但无法使其工作。

2 个答案:

答案 0 :(得分:1)

仅仅为了完整起见,回答@Nico评论中提出的问题,这是2012年的解决方案(我知道OP使用的是2008r2):

with x as (
    select *,
    lag(dt) over(order by dt) as lag_dt,
    lag(course) over(order by dt) as lag_course
    from room
),
y as (
    select *,
    sum(case when course<>lag_course then 1 else 0 end) over(order by dt) as grp
    from x
)
select min(course), min(dt), max(dt)
from y
group by grp

答案 1 :(得分:0)

不完全是您要求的结果集,但我认为结果本身符合您的想法:

with "cte" as 
(
select 
    rn = row_number() over ( order by dt )
    , * 
from room
)
,"preprocessed" as 
(
select
    "current"."course"
    , startDate = case when "predecessor"."id" is null then "current"."dt" else null end
    , endDate = case when "successor"."id" is null then "current"."dt" else null end
    , "current"."dt"
from 
    "cte" as "current"
    left join "cte" as predecessor
        on 1 = 1
        and "current"."id" = predecessor."id"
        and "current"."course" = predecessor."course"
        and "current"."rn" -1 = predecessor."rn"

    left join "cte" as successor
        on 1 = 1
        and "current"."id" = successor."id"
        and "current"."course" = successor."course"
        and "current"."rn" +1 = successor."rn"
), "pvt" as
(
select
    "course"
    , "dt"
    , "type"
from
    ( select "course", "startDate", "endDate"  from "preprocessed" ) as data
     unpivot ( "dt" for "type" in ( "startDate", "endDate")) as pvt
)
select * from 
    "pvt"

See SQL-Fiddle.