SQL查询覆盖日期范围

时间:2013-08-29 03:10:18

标签: sql oracle date range

Oracle 11i - 查找将创建一组日期范围的查询,这些日期范围允许CUSTOM值覆盖STANDARD值,并将STANDARD值保留在不被覆盖的位置。

STANDARD
CUSTOMER_ID  START_DATE  END_DATE     VALUE
0001         02/01/2013  09/15/2013   10

CUSTOM
CUSTOMER_ID  START_DATE  END_DATE     VALUE
0001         01/15/2013  03/15/2013   20
0001         07/01/2013  07/31/2013   30

Desired Result
CUSTOMER_ID  START_DATE  END_DATE     VALUE
0001         02/01/2103  03/15/2013   20
0001         03/16/2013  06/30/2013   10
0001         07/01/2013  07/31/2013   30
0001         08/01/2013  09/15/2013   10

以下是试运行的结果:

select sc.customer_id, sc.thedate as start_date,
       lead(**sc.thedate**) over (partition by sc.customer_id order by sc.thedate) as end_date,
       sc.value
from (select customer_id, start_date as thedate, value
      from standard
      union all
      select customer_id, start_date, value
      from custom
      union all
      select s.customer_id, c.end_date + 1, s.value
      from custom c join
           standard s
           on c.customer_id = s.customer_id
      union all
      select customer_id, end_date, NULL
      from standard
     ) sc
where value is not NULL;

CUSTOMER_ID     START_DATE              END_DATE                VALUE
0001            15-JAN-13 12.00.00 AM   01-FEB-13 12.00.00 AM   20
0001            01-FEB-13 12.00.00 AM   16-MAR-13 12.00.00 AM   10
0001            16-MAR-13 12.00.00 AM   01-JUL-13 12.00.00 AM   10
0001            01-JUL-13 12.00.00 AM   01-AUG-13 12.00.00 AM   30
0001            01-AUG-13 12.00.00 AM                           10

1 个答案:

答案 0 :(得分:0)

这是一种方法。将数据分解为值开始时的每个日期(对于每个客户)。然后使用Oracle分析函数将数据组合在一起。日期是“价值”的开始。然后使用lead()获取下一个日期。

select sc.customer_id, sc.thedate as start_date,
       lead(sc.start_date) over (partition by sc.customer_id order by sc.thedate) as end_date,
       sc.value
from (select s.customer_id, s.start_date as thedate, s.value
      from standard
      union all
      select c.customer_id, c.start_date, c.value
      from custom
      union all
      select s.customer_id, c.end_date + 1, s.value
      from custom c join
           standard s
           on c.customer_id = s.customer_id
      union all
      select s.customer_id, s.end_date, NULL
      from standard
     ) sc
where value is not NULL;

请注意,这包括end_date的额外记录,您不需要作为最后一行。这标记有NULL值,该值在外部查询中被过滤掉。