【问题标题】:SQL query to overlay date range覆盖日期范围的 SQL 查询
【发布时间】:2013-08-29 03:10:18
【问题描述】:

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

【问题讨论】:

    标签: sql oracle date range


    【解决方案1】:

    这是一种方法。将数据分解为值开始的每个日期(针对每个客户)。然后使用 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 值标记的,该值在外部查询中被过滤掉。

    【讨论】:

    • 谢谢,我会研究这个解决方案和你在亚马逊上的 SQL/Excel 书。看起来它在六年左右后仍然得到很好的评价。有什么推荐的补充剂吗?
    • 对@Gordon 问题添加了修改和结果
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多