如何在日期范围之间为每个月创建动态记录

时间:2017-12-21 14:21:13

标签: sql oracle date period

我在表cp中有以下日期:

start_date: 01/01/2017, end_date: 01/08/2017;
start_date: 01/04/2017, end_date: 01/07/2017

我想在这些时段之间动态创建每月的记录。它尝试了以下查询,但我不明白它为什么不起作用。

select add_months(cp.end_date, rownum-1) which_month, id
FROM    (select '1' as id, 
            to_date('01/01/2017', 'DD/MM/YYYY') start_date,
            to_date('01/08/2017', 'DD/MM/YYYY') end_date
    from dual
    UNION
    select  '2' as id, 
            to_date('01/04/2017', 'DD/MM/YYYY') start_date,
            to_date('01/07/2017', 'DD/MM/YYYY') end_date
    from dual) cp, all_objects
WHERE ROWNUM <= months_between(cp.end_date, add_months(cp.start_date, -1));

你能帮助我吗?

2 个答案:

答案 0 :(得分:0)

  

我不明白为什么它不起作用。

ROWNUM是结果集生成的伪列;它不像你想象的那样工作。

一个解决方案 - 有几个但是这是最接近行业标准的 - 是使用connect by level技巧:

select '1' as id, 
        add_months(date '2017-01-01', (level-1) ) as which_month
from dual
connect by level <= months_between(date '2017-08-01', date '2017-01-01')+1

months_between()接受参数(end_date, start_date) - 你需要在该数字上加一个来获得结束日期。

  

“等级技巧是否仍有效?”

排序。还有一个必要的技巧来阻止CONNECT BY生成产品:

select id, 
        add_months(start_date, level-1 ) as which_month
from t23
connect by level <= months_between(end_date , start_date)+1
    --  these two lines required to avoid the need for DISTINCT
    and id = prior id 
    and prior sys_guid() is not null
order by 1, 2
;

this article

答案 1 :(得分:0)

使用APC的答案,我要感谢,我能够创建以下查询:

select distinct add_months(cp.start_date, level-1) which_month, id
FROM    (select '1' as id, 
        to_date('01/01/2017', 'DD/MM/YYYY') start_date,
        to_date('01/08/2017', 'DD/MM/YYYY') end_date
    from dual
    UNION
    select  '2' as id, 
        to_date('01/04/2017', 'DD/MM/YYYY') start_date,
        to_date('01/07/2017', 'DD/MM/YYYY') end_date
   from dual) cp
connect by level <= months_between(cp.end_date, cp.start_date) + 1
order by id asc, which_month asc;

我必须在第一个select语句中使用distinct,但它为每个月(在各自的时间段内)表'cp'动态记录中的每个句点创建。

更新

使用级别技巧,我能够构建解决方案:

select add_months(cp.start_date, level-1) which_month, id
FROM    (select '1' as id, 
        to_date('01/01/2017', 'DD/MM/YYYY') start_date,
        to_date('01/08/2017', 'DD/MM/YYYY') end_date
    from dual
    UNION
    select  '2' as id, 
        to_date('01/04/2017', 'DD/MM/YYYY') start_date,
        to_date('01/07/2017', 'DD/MM/YYYY') end_date
    from dual) cp
connect by level <= months_between(cp.end_date, cp.start_date) + 1
and id = prior id
and prior sys_guid() is not null
order by id asc, which_month asc;