sql – 加入重叠的日期范围

前端之家收集整理的这篇文章主要介绍了sql – 加入重叠的日期范围前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要加入表A和表B来创建表C.

表A和表B存储ID的状态标志.状态标志(A_Flag和B_Flag)可能会随时更改,因此一个ID可以包含多个行,表示ID状态的历史记录.特定ID的标志可以彼此独立地改变,这可能导致表A中的一行属于表B中的多行,反之亦然.

生成的表(表C)需要是涵盖ID生活(01/01 / 2008-18 / 08/2008)中的每个日期的唯一日期范围的列表,以及每个日期范围的A_Flag和B_Flag值.

实际的表包含数百个ID,每个ID每个表具有不同数量的行.

我可以访问sql和SAS工具来实现最终的结果.

Source - Table A
ID  Start           End     A_Flag
1   01/01/2008  23/03/2008  1
1   23/03/2008  15/06/2008  0
1   15/06/2008  18/08/2008  1

Source - Table B
ID  Start           End     B_Flag
1   19/01/2008  17/02/2008  1
1   17/02/2008  15/06/2008  0
1   15/06/2008  18/08/2008  1

Result - Table C
ID  Start           End  A_Flag B_Flag
1   01/01/2008  19/01/2008  1   0
1   19/01/2008  17/02/2008  1   1
1   17/02/2008  23/03/2008  1   0
1   23/03/2008  15/06/2008  0   0
1   15/06/2008  18/08/2008  1   1

解决方法

您提出的问题可以在一个没有非标准扩展的sql语句中解决.

最重要的是要认识到,开始对中的日期每个都表示一个时间跨度的潜在开始或结束点,在该时间段期间,旗标对将为真.实际上并不重要,一个日期是“开始”,另一个是“结束”;任何日期都是一个时间分隔符,它既可以结束前一个时期,也可以开始另一个.构造一组最小时间间隔,并将它们连接到表以查找在每个间隔期间获得的标志.

我把你的例子(和一个解决方案)添加到我的Canonical SQL页面.看到有详细的讨论.对于SO来说,这是查询本身

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,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

猜你在找的MsSQL相关文章