Oracle中的递归查询

时间:2016-05-31 00:23:23

标签: sql oracle oracle11g recursive-query

您好我有以下查询...

我希望有一个以下数据集,只有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 个答案:

答案 0 :(得分:2)

Oracle安装程序

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 

答案 1 :(得分:1)

您在查询时遇到错误,因为在联合的下方,您使用的是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