Oracle 递归查询 - 日期
Oracle Recursive Query - Dates
我将两组日期传递到查询中,我想找到两组日期之间的所有 months/years。
当我尝试这个时:
WITH CTE_Dates (cte_date) AS (
SELECT cast(date '2014-01-27' as date) from dual
UNION ALL
SELECT cast(ADD_MONTHS(TRUNC(cte_date, 'MONTH'),1) as date)
FROM CTE_Dates
WHERE ( TO_DATE(ADD_MONTHS(TRUNC(cte_date, 'MONTH'), 1)) BETWEEN TO_DATE ('27-01-2014','DD-MM-YYYY') AND TO_DATE ('27-04-2014','DD-MM-YYYY'))
OR
( TO_DATE(ADD_MONTHS(TRUNC(cte_date, 'MONTH'), 1)) BETWEEN TRUNC(TO_DATE('27-11-2014','DD-MM-YYYY'), 'MONTH') AND TO_DATE ('27-01-2015','DD-MM-YYYY'))
)
SELECT * from CTE_Dates
我得到:
27-JAN-14
01-FEB-14
01-MAR-14
01-APR-14
我还想得到:
01-NOV-14
01-DEC-14
01-JAN-15
WHERE 子句的 OR 部分似乎被忽略了。
关于如何创建此查询的建议?
谢谢
科里
你现在拥有的问题(除了额外的 cast()
和 to_date()
调用)是在第四次迭代时两个条件都为假,因此递归停止;没有什么可以让它跳过一点然后重新拾起,否则它会永远持续下去。我不认为你可以在递归中实现这两个范围。
你可以把你想要的最新日期放在递归部分,然后过滤你想要的两个范围:
WITH CTE_Dates (cte_date) AS (
SELECT date '2014-01-27' from dual
UNION ALL
SELECT ADD_MONTHS(TRUNC(cte_date, 'MONTH'), 1)
FROM CTE_Dates
WHERE ADD_MONTHS(TRUNC(cte_date, 'MONTH'), 1) <= date '2015-01-27'
)
SELECT * from CTE_Dates
WHERE cte_date BETWEEN date '2014-01-27' AND date '2014-04-27'
OR cte_date BETWEEN date '2014-11-27' AND date '2015-01-27';
CTE_DATE
---------
27-JAN-14
01-FEB-14
01-MAR-14
01-APR-14
01-DEC-14
01-JAN-15
6 rows selected
您可以用开始日期和结束日期对替换硬编码值。如果范围可能重叠或第二个范围可能(或结束)在第一个范围之前,您可以选择较高的日期:
WHERE ADD_MONTHS(TRUNC(cte_date, 'MONTH'), 1)
<= greatest(date '2015-01-27', date '2014-04-27')
...虽然这只对变量有意义,对固定值没有意义。
我将两组日期传递到查询中,我想找到两组日期之间的所有 months/years。
当我尝试这个时:
WITH CTE_Dates (cte_date) AS (
SELECT cast(date '2014-01-27' as date) from dual
UNION ALL
SELECT cast(ADD_MONTHS(TRUNC(cte_date, 'MONTH'),1) as date)
FROM CTE_Dates
WHERE ( TO_DATE(ADD_MONTHS(TRUNC(cte_date, 'MONTH'), 1)) BETWEEN TO_DATE ('27-01-2014','DD-MM-YYYY') AND TO_DATE ('27-04-2014','DD-MM-YYYY'))
OR
( TO_DATE(ADD_MONTHS(TRUNC(cte_date, 'MONTH'), 1)) BETWEEN TRUNC(TO_DATE('27-11-2014','DD-MM-YYYY'), 'MONTH') AND TO_DATE ('27-01-2015','DD-MM-YYYY'))
)
SELECT * from CTE_Dates
我得到:
27-JAN-14
01-FEB-14
01-MAR-14
01-APR-14
我还想得到:
01-NOV-14
01-DEC-14
01-JAN-15
WHERE 子句的 OR 部分似乎被忽略了。
关于如何创建此查询的建议?
谢谢 科里
你现在拥有的问题(除了额外的 cast()
和 to_date()
调用)是在第四次迭代时两个条件都为假,因此递归停止;没有什么可以让它跳过一点然后重新拾起,否则它会永远持续下去。我不认为你可以在递归中实现这两个范围。
你可以把你想要的最新日期放在递归部分,然后过滤你想要的两个范围:
WITH CTE_Dates (cte_date) AS (
SELECT date '2014-01-27' from dual
UNION ALL
SELECT ADD_MONTHS(TRUNC(cte_date, 'MONTH'), 1)
FROM CTE_Dates
WHERE ADD_MONTHS(TRUNC(cte_date, 'MONTH'), 1) <= date '2015-01-27'
)
SELECT * from CTE_Dates
WHERE cte_date BETWEEN date '2014-01-27' AND date '2014-04-27'
OR cte_date BETWEEN date '2014-11-27' AND date '2015-01-27';
CTE_DATE
---------
27-JAN-14
01-FEB-14
01-MAR-14
01-APR-14
01-DEC-14
01-JAN-15
6 rows selected
您可以用开始日期和结束日期对替换硬编码值。如果范围可能重叠或第二个范围可能(或结束)在第一个范围之前,您可以选择较高的日期:
WHERE ADD_MONTHS(TRUNC(cte_date, 'MONTH'), 1)
<= greatest(date '2015-01-27', date '2014-04-27')
...虽然这只对变量有意义,对固定值没有意义。