根据从到日期生成一系列记录
Generate a range of records depending on from-to dates
我有 table 条这样的记录:
项目
来自
到
一个
2018-01-03
2018-03-16
B
2021-05-25
2021-11-10
select 的输出应该如下所示:
项目
月份
年
一个
01
2018
一个
02
2018
一个
03
2018
B
05
2021
B
06
2021
B
07
2021
B
08
2021
另外,范围不能超过当前月份。在上面的示例中,我们假设当天是 2021-08-01。
我正在尝试做类似于 THIS with CONNECT BY LEVEL 的事情,但是一旦我也 select 我的 table 在 dual 旁边并尝试对记录进行排序 select离子永远不会完成。我还必须加入其他几个 tables 到 selection,但我认为这不会有什么不同。
非常感谢你的帮助。
它是行生成器,但不像你做的那样;很可能您在我的查询(或他们的替代项)中缺少第 11 - 16 行。
SQL> with test (item, date_from, date_to) as
2 -- sample data
3 (select 'A', date '2018-01-03', date '2018-03-16' from dual union all
4 select 'B', date '2021-05-25', date '2021-11-10' from dual
5 )
6 -- query that returns desired result
7 select item,
8 extract(month from (add_months(date_from, column_value - 1))) month,
9 extract(year from (add_months(date_from, column_value - 1))) year
10 from test cross join
11 table(cast(multiset
12 (select level
13 from dual
14 connect by level <=
15 months_between(trunc(least(sysdate, date_to), 'mm'), trunc(date_from, 'mm')) + 1
16 ) as sys.odcinumberlist))
17 order by item, year, month;
ITEM MONTH YEAR
----- ---------- ----------
A 1 2018
A 2 2018
A 3 2018
B 5 2021
B 6 2021
B 7 2021
B 8 2021
7 rows selected.
SQL>
递归 CTE 是解决此类问题的标准 SQL 方法。在 Oracle 中,这看起来像:
with cte(item, fromd, tod) as (
select item, fromd, tod
from t
union all
select item, add_months(fromd, 1), tod
from cte
where add_months(fromd, 1) < last_day(tod)
)
select item, extract(year from fromd) as year, extract(month from fromd) as month
from cte
order by item, fromd;
Here 是一个 db<>fiddle.
我有 table 条这样的记录:
项目 | 来自 | 到 |
---|---|---|
一个 | 2018-01-03 | 2018-03-16 |
B | 2021-05-25 | 2021-11-10 |
select 的输出应该如下所示:
项目 | 月份 | 年 |
---|---|---|
一个 | 01 | 2018 |
一个 | 02 | 2018 |
一个 | 03 | 2018 |
B | 05 | 2021 |
B | 06 | 2021 |
B | 07 | 2021 |
B | 08 | 2021 |
另外,范围不能超过当前月份。在上面的示例中,我们假设当天是 2021-08-01。
我正在尝试做类似于 THIS with CONNECT BY LEVEL 的事情,但是一旦我也 select 我的 table 在 dual 旁边并尝试对记录进行排序 select离子永远不会完成。我还必须加入其他几个 tables 到 selection,但我认为这不会有什么不同。
非常感谢你的帮助。
它是行生成器,但不像你做的那样;很可能您在我的查询(或他们的替代项)中缺少第 11 - 16 行。
SQL> with test (item, date_from, date_to) as
2 -- sample data
3 (select 'A', date '2018-01-03', date '2018-03-16' from dual union all
4 select 'B', date '2021-05-25', date '2021-11-10' from dual
5 )
6 -- query that returns desired result
7 select item,
8 extract(month from (add_months(date_from, column_value - 1))) month,
9 extract(year from (add_months(date_from, column_value - 1))) year
10 from test cross join
11 table(cast(multiset
12 (select level
13 from dual
14 connect by level <=
15 months_between(trunc(least(sysdate, date_to), 'mm'), trunc(date_from, 'mm')) + 1
16 ) as sys.odcinumberlist))
17 order by item, year, month;
ITEM MONTH YEAR
----- ---------- ----------
A 1 2018
A 2 2018
A 3 2018
B 5 2021
B 6 2021
B 7 2021
B 8 2021
7 rows selected.
SQL>
递归 CTE 是解决此类问题的标准 SQL 方法。在 Oracle 中,这看起来像:
with cte(item, fromd, tod) as (
select item, fromd, tod
from t
union all
select item, add_months(fromd, 1), tod
from cte
where add_months(fromd, 1) < last_day(tod)
)
select item, extract(year from fromd) as year, extract(month from fromd) as month
from cte
order by item, fromd;
Here 是一个 db<>fiddle.