2016-05-31 81 views
0

嗨,我有以下查詢...Oracle中的遞歸查詢

我想要一個下面的數據集,它只有4列,被查詢以獲得項目。項目由前一行分隔,與當前行start_date不具有相同的end_date。所以前三行將在同一個項目中。第二個項目是下兩行,項目3和4將是倒數第二和最後一行。

DAYS,TASK_ID,START_DATE,END_DATE 
NULL,1,10/1/2015,10/2/2015 
0,2,10/2/2015,10/3/2015 
0,3,10/3/2015,10/4/2015 
9,4,10/13/2015,10/14/2015 
0,5,10/14/2015,10/15/2015 
13,6,10/28/2015,10/29/2015 
1,7,10/30/2015,10/31/2015 

所以輸出會是什麼樣子

PROJECT,DAYS,TASK_ID,START_DATE,END_DATE 
1,NULL,1,10/1/2015,10/2/2015 
1,0,2,10/2/2015,10/3/2015 
1,0,3,10/3/2015,10/4/2015 
2,9,4,10/13/2015,10/14/2015 
2,0,5,10/14/2015,10/15/2015 
3,13,6,10/28/2015,10/29/2015 
4,1,7,10/30/2015,10/31/2015 

我是一個SQL Server的建築師,我已經做了SQL Server查詢,但我在Oracle查詢得到錯誤。這是我迄今在Oracle中所擁有的。

WITH projectsNumbered (Project, Task_Id, Start_Date, End_Date, Days) AS 
(SELECT 1 As "Project" 
     , Task_Id 
     , Start_Date 
     , End_Date 
     , Days 
    FROM daysBetweenTasks 
    WHERE Task_Id = 1 
    UNION ALL 
    SELECT 
     CASE WHEN COALESCE(pN.Days,0) = 0 THEN pN.Project 
      ELSE pN.Project + 1 
     END AS "Project" 
     , pN.Task_Id 
     , pN.Start_Date 
     , pN.End_Date 
     , pN.Days 
    FROM projectsNumbered pN 
    JOIN daysBetweenTasks d on p.task_Id = pN.task_Id + 1 
) 
--SEARCH DEPTH FIRST BY Task_Id SET order1 
CYCLE Task_Id SET cycle TO '1' DEFAULT 0 
SELECT * 
FROM projectsNumbered 

但我只得到兩行返回。我在發生錯誤後添加了Cycle Clause。我認爲oracle dba可能可以處理這個問題?順便說一句,我正在使用11g Express。

回答

2

甲骨文設置

CREATE TABLE daysBetweenTasks (DAYS,TASK_ID,START_DATE,END_DATE) AS 
SELECT NULL, 1, DATE '2015-10-01', DATE '2015-10-02' FROM DUAL UNION ALL 
SELECT 0, 2, DATE '2015-10-02', DATE '2015-10-03' FROM DUAL UNION ALL 
SELECT 0, 3, DATE '2015-10-03', DATE '2015-10-04' FROM DUAL UNION ALL 
SELECT 9, 4, DATE '2015-10-13', DATE '2015-10-14' FROM DUAL UNION ALL 
SELECT 0, 5, DATE '2015-10-14', DATE '2015-10-15' FROM DUAL UNION ALL 
SELECT 13, 6, DATE '2015-10-28', DATE '2015-10-29' FROM DUAL UNION ALL 
SELECT 1, 7, DATE '2015-10-30', DATE '2015-10-31' FROM DUAL; 

查詢

SELECT DENSE_RANK() OVER (ORDER BY CONNECT_BY_ROOT(task_id)) AS project, 
     days, 
     task_id, 
     start_date, 
     end_date 
FROM (
    SELECT d.*, 
     LAG(end_date) OVER (ORDER BY task_id) AS prev_end_date 
    FROM daysBetweenTasks d 
) d 
START WITH prev_end_date IS NULL 
OR   prev_end_date <> start_date 
CONNECT BY PRIOR end_date = start_date; 

輸出

PROJECT  DAYS TASK_ID START_DATE   END_DATE   
---------- ---------- ---------- ------------------- ------------------- 
     1      1 2015-10-01 00:00:00 2015-10-02 00:00:00 
     1   0   2 2015-10-02 00:00:00 2015-10-03 00:00:00 
     1   0   3 2015-10-03 00:00:00 2015-10-04 00:00:00 
     2   9   4 2015-10-13 00:00:00 2015-10-14 00:00:00 
     2   0   5 2015-10-14 00:00:00 2015-10-15 00:00:00 
     3   13   6 2015-10-28 00:00:00 2015-10-29 00:00:00 
     4   1   7 2015-10-30 00:00:00 2015-10-31 00:00:00 
+0

你知道你將如何使用它裏面像查詢遞歸的SQL Server?用cte的錨和遞歸部分? –

1

你得到一個錯誤Ø在查詢中,因爲在union的下面,所有使用的都是pN.task_id而不是d.task_id,這是一個無限循環。 這是它應該是什麼樣子:

WITH projectsNumbered (Project, Task_Id, Start_Date, End_Date, Days) AS 
(SELECT 1 As "Project" 
     , Task_Id 
     , Start_Date 
     , End_Date 
     , Days 
    FROM daysBetweenTasks 
    WHERE Task_Id = 1 
    UNION ALL 
    SELECT 
     CASE WHEN COALESCE(d.Days,0) = 0 THEN pN.Project 
      ELSE pN.Project + 1 
     END AS "Project" 
     , d.Task_Id 
     , d.Start_Date 
     , d.End_Date 
     , d.Days 
    FROM projectsNumbered pN 
    JOIN daysBetweenTasks d on d.task_Id = pN.task_Id + 1 
) 
SELECT * 
FROM projectsNumbered; 

OUPUT

PROJECT TASK_ID START_DATE END_DATE DAYS 
1   1  01-OCT-15 02-OCT-15   
1   2  02-OCT-15 03-OCT-15 0  
1   3  03-OCT-15 04-OCT-15 0  
2   4  13-OCT-15 14-OCT-15 9  
2   5  14-OCT-15 15-OCT-15 0  
3   6  28-OCT-15 29-OCT-15 13  
4   7  30-OCT-15 31-OCT-15 1  
+1

謝謝你,我真的這樣做,但我有不正確地排列的列。它只給了我一行回報。瘋狂的錯誤男人這樣的菜鳥 –