Join overlapping date ranges

前端 未结 4 1389
半阙折子戏
半阙折子戏 2021-02-08 06:16

I need to join table A and table B to create table C.

Table A and Table B store status flags for the IDs. The status flags (A_Flag and B_Flag) can change from time to ti

4条回答
  •  夕颜
    夕颜 (楼主)
    2021-02-08 06:50

    The problem you posed can be solved in one SQL statement without nonstandard extensions.

    The most important thing to recognize is that the dates in the begin-end pairs each represent a potential starting or ending point of a time span during which the flag pair will be true. It actually doesn't matter that one date is a "begin" and another and "end"; any date is a time delimiter that does both: it ends a prior period and begins another. Construct a set of minimal time intervals, and join them to the tables to find the flags that obtained during each interval.

    I added your example (and a solution) to my Canonical SQL page. See there for a detailed discussion. In fairness to SO, here's the query itself

    with D (ID, bound) as (
        select   ID 
           , case T when 's' then StartDate else EndDate end as bound
        from  (
        select ID, StartDate, EndDate from so.A 
        UNION
        select ID, StartDate, EndDate from so.B
        ) as U
        cross join (select 's' as T union select 'e') as T
    )
    select P.*, a.Flag as A_Flag, b.Flag as B_Flag
    from (
        select s.ID, s.bound as StartDate, min(e.bound) as EndDate
        from D as s join D as e 
        on s.ID = e.ID 
        and s.bound < e.bound
        group by s.ID, s.bound
    ) as P
    left join so.A as a
    on  P.ID = a.ID 
    and a.StartDate <= P.StartDate and P.EndDate <= a.EndDate
    left join so.B as b
    on  P.ID = b.ID 
    and b.StartDate <= P.StartDate and P.EndDate <= b.EndDate
    order by P.ID, P.StartDate, P.EndDate
    

提交回复
热议问题