使用CTE Oracle生成日期范围

时间:2017-02-28 13:03:39

标签: oracle common-table-expression recursive-query

我想使用Oracle中的递归WITH子句在两个不同日期之间生成一系列天数。

WITH CTE_Dates (cte_date) AS
  ( SELECT CAST(TO_DATE('10-02-2017', 'DD-MM-YYYY') AS DATE) cte_date FROM dual
  UNION ALL
  SELECT CAST( (cte_date + 1) AS DATE) cte_date
  FROM CTE_Dates
  WHERE TRUNC(cte_date) + 1 <= TO_DATE('20-02-2017', 'DD-MM-YYYY')
  )
SELECT * FROM CTE_Dates

返回的结果完全不是预期的结果:

10-02-2017
09-02-2017
08-02-2017
07-02-2017
06-02-2017
... (unlimited)

预期结果:

10-02-2017
11-02-2017
...
19-02-2017
20-02-2017

Oracle Database 11g快捷版11.2.0.2.0版 - 64位生产。

修改 据我所知,这是Oracle中已知的Bug,该错误存在于Oracle 11.2.0.2中,并在11.2.0.3中得到修复。

Altarnative解决方案:

SELECT TRUNC (TO_DATE('10-02-2017', 'DD-MM-YYYY') + ROWNUM -1) dt
  FROM DUAL
 CONNECT BY ROWNUM  <= (TO_DATE('20-02-2017', 'DD-MM-YYYY') - (TO_DATE('10-02-2017', 'DD-MM-YYYY')))

4 个答案:

答案 0 :(得分:5)

这是Oracle 11中递归CTE的一个已知错误(特别是关于日期算术)。在Oracle 12中已修复。正是这种行为:无论您在代码中添加还是减去,引擎总是减去,它都不会添加。

编辑:实际上,正如Alex Poole在对原始帖子的评论中指出的那样,该错误通过Oracle 11.2.0.2存在,并在11.2.0.3中得到修复。 结束修改

唉,我不是付费客户,所以我不能引用章节和经文,但是通过一点谷歌搜索,你会找到这个的链接(包括在OTN,我参与讨论这个和其他的一些线程)递归CTE中的错误 - 一些是修复的,一些仍然是Oracle 12.1中的错误。)

已添加 - 以下是其中一项讨论:https://community.oracle.com/thread/3974408

答案 1 :(得分:2)

除非您确实需要使用WITH子句,否则还有另一种解决方案可以通过使用CONNECT BY子句来获得预期结果。

SELECT TO_DATE('10-02-2017', 'DD-MM-YYYY') AS date_range
  FROM dual
UNION ALL
SELECT TO_DATE('10-02-2017', 'DD-MM-YYYY') + LEVEL  
  FROM dual 
  CONNECT BY LEVEL <= (TO_DATE('20-02-2017', 'DD-MM-YYYY') - TO_DATE('10-02-2017', 'DD-MM-YYYY'));

答案 2 :(得分:2)

可能递归的反向顺序解决了这个问题:

with cte_dates (cte_date) as ( 
    select cast(to_date('20-02-2017', 'DD-MM-YYYY') as date) cte_date from dual
    union all
    select  cast((cte_date - 1) as date)  cte_date
    from cte_dates
    where cast(cte_date as date) > to_date('10-02-2017', 'DD-MM-YYYY')
    )
select * from cte_dates 
order by cte_date 
;

2017-02-10
2017-02-11
2017-02-12
...
2017-02-18
2017-02-19
2017-02-20

注意:由于RCTE在11gR2中还有另一个错误

,所以投日期为所需日期

Old discussion here

答案 3 :(得分:0)

你不需要一个递归的WITH子句,你只需要一个行数&gt;的表。要生成的日期数:

$('input:checkbox').change(
        function () {
            if ($(this).is(':checked')) {
                $('<li />').appendTo('#div ul').text($(this).val());
            }
            else {

                if ($('#div ul').has('<li />')) {
                    $('li').remove();
                }
            }
        });