2017-04-06 25 views
0

比方說,我有一個表數據範圍麻煩與Oracle的CONNECT BY和日期範圍

create table ranges (id number, date_from date, date_to date); 
insert into ranges values (1, to_date('01.01.2017', 'dd.mm.rrrr'), to_date('03.01.2017', 'dd.mm.rrrr')); 
insert into ranges values (2, to_date('05.02.2017', 'dd.mm.rrrr'), to_date('08.02.2017', 'dd.mm.rrrr')); 

和我的輸出應該在這些範圍

id | the_date 
---------------- 
1 | 01.01.2017 
1 | 02.01.2017 
1 | 03.01.2017 
2 | 05.02.2017 
2 | 06.02.2017 
2 | 07.02.2017 
2 | 08.02.2017 

但是通過連接一排,每日期給我ORA-01436 Connect by Loop

SELECT connect_by_root(id), Trunc(date_from, 'dd') + LEVEL - 1 AS the_date 
FROM ranges 
CONNECT BY PRIOR id = id AND Trunc(date_from, 'dd') + LEVEL - 1 <= Trunc(date_to, 'dd') 
ORDER BY id, the_date 

怎麼了?

回答

3

您可以添加對非確定性函數的調用,例如,

AND PRIOR dbms_random.value IS NOT NULL 

所以就變成:

SELECT connect_by_root(id), Trunc(date_from, 'dd') + LEVEL - 1 AS the_date 
FROM ranges 
CONNECT BY PRIOR id = id 
AND PRIOR dbms_random.value IS NOT NULL 
AND Trunc(date_from, 'dd') + LEVEL - 1 <= Trunc(date_to, 'dd') 
ORDER BY id, the_date; 

CONNECT_BY_ROOT(ID) THE_DATE 
------------------- --------- 
        1 01-JAN-17 
        1 02-JAN-17 
        1 03-JAN-17 
        2 05-FEB-17 
        2 06-FEB-17 
        2 07-FEB-17 
        2 08-FEB-17 

7 rows selected. 

還有爲什麼有必要in this Oracle Community post的說明;使用sys_guid()而不是dbms_random.value,但原理是相同的。

如果你在11gR2中或更高版本,你可以使用recursive subquery factoring代替:

WITH rcte (root_id, the_date, date_to) AS (
    SELECT id, date_from, date_to 
    FROM ranges 
    UNION ALL 
    SELECT root_id, the_date + 1, date_to 
    FROM rcte 
    WHERE the_date < date_to 
) 
SELECT root_id, the_date 
FROM rcte 
ORDER BY root_id, the_date; 

    ROOT_ID THE_DATE 
---------- --------- 
     1 01-JAN-17 
     1 02-JAN-17 
     1 03-JAN-17 
     2 05-FEB-17 
     2 06-FEB-17 
     2 07-FEB-17 
     2 08-FEB-17 

7 rows selected. 
+0

我使用遞歸子查詢。尼斯。有時候,甲骨文有點令人沮喪:-( – Basti