例如,我有一个表名 test_cross_months,数据如下:
id | 开始日期 | 结束日期 |
---|---|---|
44 | 2020-01-04 | 2020-01-04 |
44 | 2020-01-30 | 2020-02-10 |
44 | 2020-02-27 | 2020-03-03 |
预期结果:
id | 开始日期 | 结束日期 |
---|---|---|
44 | 2020-01-04 | 2020-01-04 |
44 | 2020-01-30 | 2020-01-31 |
44 | 2020-02-01 | 2020-02-10 |
44 | 2020-02-27 | 2020-02-29 |
44 | 2020-03-01 | 2020-03-03 |
所以对于 |44|2020-01-30 |2020-02-10| 应该有两行,从 30-Jan-2020 到 31-Jan-2020 和 1-Feb-2020 到 10-Feb-2020
我尝试将结束日期与 start_date 的最后一天进行比较,但由于没有为 end_date 范围创建新行而面临问题。
有没有人可以提出解决方案?
答案 0 :(得分:2)
您可以使用递归查询(无论您的范围跨越多少个月都可以使用):
WITH months ( id, start_date, end_date, final_date ) AS (
SELECT id,
start_date,
LEAST( LAST_DAY( start_date ), end_date ),
end_date
FROM table_name
UNION ALL
SELECT id,
end_date + INTERVAL '1' DAY,
LEAST( ADD_MONTHS( end_date, 1 ), final_date ),
final_date
FROM months
WHERE end_date < final_date
)
SEARCH DEPTH FIRST BY final_date SET dt_order
SELECT id,
start_date,
end_date
FROM months;
对于样本数据:
CREATE TABLE table_name (id, start_date, end_date) AS
SELECT 44, DATE '2020-01-04', DATE '2020-01-04' FROM DUAL UNION ALL
SELECT 44, DATE '2020-01-30', DATE '2020-02-10' FROM DUAL UNION ALL
SELECT 44, DATE '2020-02-27', DATE '2020-03-03' FROM DUAL;
输出:
<块引用>ID | START_DATE | END_DATE |
---|---|---|
44 | 2020-01-04 00:00:00 | 2020-01-04 00:00:00 |
44 | 2020-01-30 00:00:00 | 2020-01-31 00:00:00 |
44 | 2020-02-01 00:00:00 | 2020-02-10 00:00:00 |
44 | 2020-02-27 00:00:00 | 2020-02-29 00:00:00 |
44 | 2020-03-01 00:00:00 | 2020-03-03 00:00:00 |
db<>fiddle here
答案 1 :(得分:0)
使用数字表和日期算术
-- example of table of numbers
with nmbrs(n) as(
select 0 from dual union all
select 1 from dual union all
select 2 from dual
)
select t.id,
case when n=0 then t.start_date else trunc(t.start_date, 'MM') + NUMTOYMINTERVAL(n, 'MONTH') end s,
case when n=MONTHS_BETWEEN(last_day(t.end_date), last_day(t.start_date)) then t.end_date
else last_day(t.start_date + NUMTOYMINTERVAL(n, 'MONTH')) end e
from test_cross_months t
join nmbrs on nmbrs.n <= MONTHS_BETWEEN(last_day(t.end_date), last_day(t.start_date))
order by t.id, s