如何在oracle中生成多行中两个日期之间的日期?[副本]

gcmastyq  于 2023-05-06  发布在  Oracle
关注(0)|答案(1)|浏览(194)

此问题已在此处有答案

Oracle SQL. Get Dates between two dates(3个答案)
Generate a range of dates using SQL(17回答)
2天前关闭。
社区在2天前审查了是否重新打开此问题,并将其关闭:
原始关闭原因未解决
我有一个表create table date_period(dt_from date, dt_to date);,我想生成1列输出,每2个日期之间的日期。
我这样写道:

select (dt_from - 1 + ROWNUM) 
from date_period 
connect by ROWNUM <= (trunc(dt_to) - trunc(dt_from) + 1)

但由于某些原因,它不能正常工作,它只在date_period表中只有1行时才有效。
我错在哪里?我该怎么解决这个问题?
例如,如果我的表中有两行:

13-FEB-2023, 15-FEB-2023
20-JUN-2023, 22-JUN-2023

我想把这个退回去:

13-FEB-2023
14-FEB-2023
15-FEB-2023
20-JUN-2023
21-JUN-2023
22-JUN-2023

但是通过我写的查询,我得到了这个:

13-FEB-23
14-FEB-23
15-FEB-23
23-JUN-23

我可以使用递归公共表表达式来实现这一点,但是如何使用connect by来实现呢?

hi3rlvi2

hi3rlvi21#

您需要在查询中使用PRIOR dt_from = dt_from,以确保生成的日期被视为行。如果不这样做,查询将在最后一个实际数据行处停止。AND PRIOR SYS_GUID() IS NOT NULL的引入是为了避免创建笛卡尔积。

CREATE TABLE date_period(dt_from DATE, dt_to DATE);

INSERT INTO date_period(dt_from, dt_to) VALUES (DATE '2023-02-13', DATE '2023-02-15');
INSERT INTO date_period(dt_from, dt_to) VALUES (DATE '2023-06-20', DATE '2023-06-22');

/*
Using a hierarchical query with the CONNECT BY clause 
to generate the dates between dt_from and dt_to for each row in the table. 
The PRIOR conditions used to prevent the query from generating a Cartesian product.
*/
SELECT dt_from + LEVEL - 1 AS dates
FROM date_period
CONNECT BY LEVEL <= dt_to - dt_from + 1
AND PRIOR dt_from = dt_from
AND PRIOR SYS_GUID() IS NOT NULL;
日期
2023年2月13日
23年2月14日
23年2月15日
23年6月20日
23年6月21日
23年6月22日

一种更“现代”和符合SQL标准的方法是采用“递归CTE”,而不是Oracle的专有语法。例如

/*
This recursive CTE generates the dates between dt_from and dt_to for each row in the table 
by repeatedly adding one day to dt_from until it is equal to dt_to.
*/
WITH date_range (dt_from, dt_to) AS (
  SELECT dt_from, dt_to FROM date_period
  UNION ALL
  SELECT dt_from + 1, dt_to FROM date_range WHERE dt_from < dt_to
)
SELECT dt_from AS dates FROM date_range ORDER BY dt_from;
日期
2023年2月13日
23年2月14日
23年2月15日
23年6月20日
23年6月21日
23年6月22日

fiddle

注意事项

我看不到任何东西可以阻止您的日期范围重叠,因此输出将重复日期。因此,为了避免这种情况,您可能需要在上述查询中采用SELECT DISTINCT
fiddle with duplicates

相关问题