我需要加入表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