如何在日期范围内为每个月动态创建记录
How to create dynamically records for each month between range of dates
我在 table 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));
你能帮帮我吗?
I don't understand why it's not working.
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)
- 您需要将该数字加一以获得结束日期。
"Would the level-trick still work ?"
有点。有一个额外的技巧可以防止 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
;
使用 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 语句中使用不同的,但它为每个月(在各自的时间段内)的 table '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;
我在 table 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));
你能帮帮我吗?
I don't understand why it's not working.
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)
- 您需要将该数字加一以获得结束日期。
"Would the level-trick still work ?"
有点。有一个额外的技巧可以防止 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
;
使用 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 语句中使用不同的,但它为每个月(在各自的时间段内)的 table '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;