具有间隔的日期的 Oracle 递归 CTE
Oracle recursive CTE for date with interval
我正在尝试创建一个递归 CTE,它每 10 分钟生成一个 date/time 并在午夜停止,但我在语法上苦苦挣扎,似乎无法让它工作。
如果有人能帮助我,我将不胜感激。在此先感谢所有回答者。
ALTER SESSION SET NLS_DATE_FORMAT = 'MMDDYYYY HH24:MI:SS';
with date_rows
(( SELECT TO_DATE('2021/08/20 18:30:25', 'YYYY/MM/DD HH24:MI:SS') as start_date FROM DUAL )
union all
select start_date+interval '10' minute
from date_rows
where start_date <
TRUNC(start_date) + INTERVAL '1' DAY)
select * from date_rows;
Something like this, I presume.
SQL> with date_rows (datum) as
2 (select cast (to_date('2021/08/20 18:30:25', 'YYYY/MM/DD HH24:MI:SS') as date)
3 from dual
4 union all
5 select cast (datum + interval '10' minute as date)
6 from date_rows
7 where datum < trunc(to_date('2021/08/20 18:30:25', 'YYYY/MM/DD HH24:MI:SS')) + interval '1' day
8 )
9 select * from date_rows;
DATUM
-----------------
08202021 18:30:25
08202021 18:40:25
08202021 18:50:25
08202021 19:00:25
08202021 19:10:25
08202021 19:20:25
08202021 19:30:25
08202021 19:40:25
08202021 19:50:25
08202021 20:00:25
08202021 20:10:25
<snip>
08202021 23:20:25
08202021 23:30:25
08202021 23:40:25
08202021 23:50:25
08212021 00:00:25
34 rows selected.
SQL>
您可以使用:
WITH inputs ( value ) AS (
SELECT TO_DATE('2021/08/20 18:30:25', 'YYYY/MM/DD HH24:MI:SS')
FROM DUAL
),
date_rows ( start_date, end_date ) AS (
SELECT value,
TRUNC(value) + INTERVAL '1' DAY
FROM inputs
UNION ALL
SELECT start_date + INTERVAL '10' MINUTE,
end_date
FROM date_rows
WHERE start_date + INTERVAL '10' MINUTE < end_date
)
SELECT start_date
FROM date_rows;
或者,如果你想复制输入值,那么你可以使用:
WITH date_rows ( start_date ) AS (
SELECT TO_DATE('2021/08/20 18:30:25', 'YYYY/MM/DD HH24:MI:SS')
FROM DUAL
UNION ALL
SELECT start_date + INTERVAL '10' MINUTE
FROM date_rows
WHERE start_date + INTERVAL '10' MINUTE
< TRUNC(TO_DATE('2021/08/20 18:30:25', 'YYYY/MM/DD HH24:MI:SS'))
+ INTERVAL '1' DAY
)
SELECT *
FROM date_rows;
注意:在递归子查询的每次迭代中,start_date
是前一个值,因此您需要检查 start_date + INTERVAL '10' MINUTE
是否在午夜之前(而不仅仅是 start_date
) 否则你将在午夜后排到最后一行。
db<>fiddle here
你的代码有什么问题:
对于非递归子查询分解子句,语法为:
WITH query_alias AS (
或
WITH query_alias (column_alias) AS (
您缺少 AS
关键字。
但是,对于递归子查询分解子句,您需要使用第二个版本并指定列别名。
第一个 SELECT
周围的 ()
括号是多余的(但不会导致错误)。
start_date < TRUNC(start_date) + INTERVAL '1' DAY)
始终为真,即使日期超过了午夜边界;所以查询将无限递归。
db<>fiddle here
我正在尝试创建一个递归 CTE,它每 10 分钟生成一个 date/time 并在午夜停止,但我在语法上苦苦挣扎,似乎无法让它工作。
如果有人能帮助我,我将不胜感激。在此先感谢所有回答者。
ALTER SESSION SET NLS_DATE_FORMAT = 'MMDDYYYY HH24:MI:SS';
with date_rows
(( SELECT TO_DATE('2021/08/20 18:30:25', 'YYYY/MM/DD HH24:MI:SS') as start_date FROM DUAL )
union all
select start_date+interval '10' minute
from date_rows
where start_date <
TRUNC(start_date) + INTERVAL '1' DAY)
select * from date_rows;
Something like this, I presume.
SQL> with date_rows (datum) as
2 (select cast (to_date('2021/08/20 18:30:25', 'YYYY/MM/DD HH24:MI:SS') as date)
3 from dual
4 union all
5 select cast (datum + interval '10' minute as date)
6 from date_rows
7 where datum < trunc(to_date('2021/08/20 18:30:25', 'YYYY/MM/DD HH24:MI:SS')) + interval '1' day
8 )
9 select * from date_rows;
DATUM
-----------------
08202021 18:30:25
08202021 18:40:25
08202021 18:50:25
08202021 19:00:25
08202021 19:10:25
08202021 19:20:25
08202021 19:30:25
08202021 19:40:25
08202021 19:50:25
08202021 20:00:25
08202021 20:10:25
<snip>
08202021 23:20:25
08202021 23:30:25
08202021 23:40:25
08202021 23:50:25
08212021 00:00:25
34 rows selected.
SQL>
您可以使用:
WITH inputs ( value ) AS (
SELECT TO_DATE('2021/08/20 18:30:25', 'YYYY/MM/DD HH24:MI:SS')
FROM DUAL
),
date_rows ( start_date, end_date ) AS (
SELECT value,
TRUNC(value) + INTERVAL '1' DAY
FROM inputs
UNION ALL
SELECT start_date + INTERVAL '10' MINUTE,
end_date
FROM date_rows
WHERE start_date + INTERVAL '10' MINUTE < end_date
)
SELECT start_date
FROM date_rows;
或者,如果你想复制输入值,那么你可以使用:
WITH date_rows ( start_date ) AS (
SELECT TO_DATE('2021/08/20 18:30:25', 'YYYY/MM/DD HH24:MI:SS')
FROM DUAL
UNION ALL
SELECT start_date + INTERVAL '10' MINUTE
FROM date_rows
WHERE start_date + INTERVAL '10' MINUTE
< TRUNC(TO_DATE('2021/08/20 18:30:25', 'YYYY/MM/DD HH24:MI:SS'))
+ INTERVAL '1' DAY
)
SELECT *
FROM date_rows;
注意:在递归子查询的每次迭代中,start_date
是前一个值,因此您需要检查 start_date + INTERVAL '10' MINUTE
是否在午夜之前(而不仅仅是 start_date
) 否则你将在午夜后排到最后一行。
db<>fiddle here
你的代码有什么问题:
对于非递归子查询分解子句,语法为:
WITH query_alias AS (
或
WITH query_alias (column_alias) AS (
您缺少
AS
关键字。但是,对于递归子查询分解子句,您需要使用第二个版本并指定列别名。
第一个
SELECT
周围的()
括号是多余的(但不会导致错误)。start_date < TRUNC(start_date) + INTERVAL '1' DAY)
始终为真,即使日期超过了午夜边界;所以查询将无限递归。
db<>fiddle here