带休息的日期:从2开3行

时间:2014-09-17 12:47:51

标签: sql oracle date

编辑:添加了一个ID,以使其更易于理解

我偶然发现了这个问题几次并且总是按PL/SQL解决它,但我想知道,如果有SQL解决方案。

有一张包含from_dateto_date的表格。每个to_date的数据都是无缝的,第二天会有一个from_date的新行。

create table test_date
(
  id number,
  from_date date,
  to_date date
)
/

insert into test_date values(1, to_date('01022003', 'ddmmyyyy'), to_date('28022003', 'ddmmyyyy'))
/

insert into test_date values(2, to_date('01032003', 'ddmmyyyy'), to_date('31032003', 'ddmmyyyy'))
/

还有另一张表打破了这段时间。

create table test_date2
(
  id number,
  from_date date,
  to_date date
)
/

insert into test_date2 values(3, to_date('05022003', 'ddmmyyyy'), to_date('10022003', 'ddmmyyyy'))
/

所以,我想要一个视图,它显示了不同列中的这个时间段和“中断”,但是在使用test_date2“中断”之后它也应该是无缝的,它应该正确显示test_date我无法做到这一点:

select typ, id, from_date, decode(typ, 1, decode(to_date+1, lead_from_date, to_date, lead_from_date-1), to_date) to_date
from(
select typ, id, from_date, to_date, lead(from_date) over (order by from_date, typ) lead_from_date
from 
(select 1 typ, id, from_date, to_date
   from test_date t
union all 
select 2 typ, id, from_date, to_date
   from test_date2 t2
   ) a
   )

我得到的是

1   1   01/02/2003  04/02/2003
2   3   05/02/2003  10/02/2003
1   2   01/03/2003  

11/02/200328/02/2003之间的时间段(test_dataid=1的行)缺失。

所以,我想要的是:

1   1   01/02/2003  04/02/2003
2   3   05/02/2003  10/02/2003
1   1   11/02/2003  28/02/2003
1   2   01/03/2003  

1 个答案:

答案 0 :(得分:0)

我认为这就是你所追求的;您没有得到相同的答案,因为您没有生成完整的日期列表。如果您为了获得唯一的日期列表而对数据进行规范化,则可以使用LEAD()LAG()查找下一个/上一个日期,然后重新生成列表。

我在这里使用UNPIVOTfrom_dateto_date转换为单个列,但4个联合将提供相同的结果:

with all_tables as (
 select *
   from test_date
  union all
 select *
   from test_date2
        )
 , all_dates as (
 select dt
   from all_tables
unpivot ( dt for dates in ( from_date, to_date ))
        )
select dt
     , lead(dt) over (order by dt) as to_date
  from all_dates;

DT         TO_DATE
---------- ----------
01/02/2003 05/02/2003
05/02/2003 10/02/2003
10/02/2003 28/02/2003
28/02/2003 01/03/2003
01/03/2003 31/03/2003
31/03/2003

6 rows selected.