2013-10-16 113 views
1

我是一個Oracle新手...相對來說...Oracle CTE尋找祖父母和兒童的孩子

我想在我已經繼承的Oracle表上使用CTE。這比我所希望的要複雜一點,因爲「最高級別」沒有明確定義。

create table testConnectBy (parent number, child number); 

insert into testConnectBy values (1, 1); 
insert into testConnectBy values (1, 11); 
insert into testConnectBy values (1, 12); 
insert into testConnectBy values (2, 2); 
insert into testConnectBy values (2, 13); 
insert into testConnectBy values (11, 11); 
insert into testConnectBy values (11, 20); 
insert into testConnectBy values (11, 21); 
insert into testConnectBy values (12, 12); 
insert into testConnectBy values (12, 22); 
insert into testConnectBy values (12, 23); 
insert into testConnectBy values (12, 24); 
insert into testConnectBy values (13, 13); 
insert into testConnectBy values (13, 30); 
insert into testConnectBy values (13, 31); 
insert into testConnectBy values (30, 30); 
insert into testConnectBy values (30, 40); 

此查詢獲取所有所需的行,但有一些重複的(這是一個問題,我想,第一部分是怎麼回事最好刪除)。我必須包含nocycle,因爲存在循環問題(parent == child)。

select * 
    from testConnectBy 
    start with parent = '1' 
    connect by nocycle prior child = parent; 

接下來的問題是,我希望能夠輸入11例如,並找出所有的父母和孩子。我不知道哪些父母或孩子與11有關。只是我需要通過使用11來找到它們。

此查詢只返回11的孩子。有沒有什麼方法可以返回兩個「方向」?

select * 
    from testConnectBy 
    start with parent = '11' 
    connect by nocycle prior child = parent; 

在此先感謝。

回答

1

對於第一個問題,請使用下面的問題。它不具有可以在路徑中進行檢查任何重複

SELECT 
      PARENT, 
      CHILD, 
      LEVEL, 
      CONNECT_BY_ISLEAF AS ISLEAF, 
      CONNECT_BY_ISCYCLE AS ISCYCLE, 
      CONNECT_BY_ROOT PARENT 
      || SYS_CONNECT_BY_PATH (CHILD, 
           ' ~ ') 
       AS PATH 
     FROM 
      TESTCONNECTBY 
     CONNECT BY 
      NOCYCLE PARENT = PRIOR CHILD 
     START WITH 
      PARENT = '1'; 

如果你想避免PARENT = CHILDREN這將返回

1 1 1 0 1 1 ~ 1 
1 11 2 0 1 1 ~ 1 ~ 11 
11 20 3 1 0 1 ~ 1 ~ 11 ~ 20 
11 21 3 1 0 1 ~ 1 ~ 11 ~ 21 
1 12 2 0 1 1 ~ 1 ~ 12 
12 22 3 1 0 1 ~ 1 ~ 12 ~ 22 
12 23 3 1 0 1 ~ 1 ~ 12 ~ 23 
12 24 3 1 0 1 ~ 1 ~ 12 ~ 24 
1 11 1 0 1 1 ~ 11 
11 20 2 1 0 1 ~ 11 ~ 20 
11 21 2 1 0 1 ~ 11 ~ 21 
1 12 1 0 1 1 ~ 12 
12 22 2 1 0 1 ~ 12 ~ 22 
12 23 2 1 0 1 ~ 12 ~ 23 
12 24 2 1 0 1 ~ 12 ~ 24 

,然後

SELECT 
      PARENT, 
      CHILD, 
      LEVEL, 
      CONNECT_BY_ISLEAF AS ISLEAF, 
      CONNECT_BY_ISCYCLE AS ISCYCLE, 
      CONNECT_BY_ROOT PARENT 
      || SYS_CONNECT_BY_PATH (CHILD, 
           ' ~ ') 
       AS PATH 
     FROM 
      (SELECT * FROM TESTCONNECTBY WHERE PARENT <> CHILD) 
     CONNECT BY 
      NOCYCLE PARENT = PRIOR CHILD 
     START WITH 
      PARENT = '1'; 

結果是

1 11 1 0 0 1 ~ 11 
11 20 2 1 0 1 ~ 11 ~ 20 
11 21 2 1 0 1 ~ 11 ~ 21 
1 12 1 0 0 1 ~ 12 
12 22 2 1 0 1 ~ 12 ~ 22 
12 23 2 1 0 1 ~ 12 ~ 23 
12 24 2 1 0 1 ~ 12 ~ 24 

Fo R您的第二個問題,你可以使用下面的代碼片段

SELECT 
     * 
FROM 
     (SELECT 
      PARENT, 
      CHILD, 
      LEVEL, 
      CONNECT_BY_ISLEAF AS ISLEAF, 
      CONNECT_BY_ISCYCLE AS ISCYCLE, 
      CONNECT_BY_ROOT PARENT 
      || SYS_CONNECT_BY_PATH (CHILD, 
           ' ~ ') 
       AS PATH 
     FROM 
      TESTCONNECTBY 
     CONNECT BY 
      NOCYCLE PARENT = PRIOR CHILD 
     START WITH 
      PARENT = '1') 
WHERE 
     PARENT = 11 
     OR CHILD = 11; 

該查詢返回

1 11 2 0 1 1 ~ 1 ~ 11 
11 20 3 1 0 1 ~ 1 ~ 11 ~ 20 
11 21 3 1 0 1 ~ 1 ~ 11 ~ 21 
1 11 1 0 1 1 ~ 11 
11 20 2 1 0 1 ~ 11 ~ 20 
11 21 2 1 0 1 ~ 11 ~ 21 

因爲父母11個孩子11.如果要排除自我的孩子,然後

SELECT 
     * 
FROM 
     (SELECT 
      PARENT, 
      CHILD, 
      LEVEL, 
      CONNECT_BY_ISLEAF AS ISLEAF, 
      CONNECT_BY_ISCYCLE AS ISCYCLE, 
      CONNECT_BY_ROOT PARENT 
      || SYS_CONNECT_BY_PATH (CHILD, 
           ' ~ ') 
       AS PATH 
     FROM 
      (SELECT * FROM TESTCONNECTBY WHERE PARENT <> CHILD) 
     CONNECT BY 
      NOCYCLE PARENT = PRIOR CHILD 
     START WITH 
      PARENT = '1') 
WHERE 
     PARENT = 11 
     OR CHILD = 11; 

將返回

1 11 1 0 0 1 ~ 11 
11 20 2 1 0 1 ~ 11 ~ 20 
11 21 2 1 0 1 ~ 11 ~ 21 
+0

感謝您的迴應。不幸的是,在你最後的查詢中,你使用了PARENT ='1'。我不會知道父母是'1'。只有'11'在層次結構中。 –

+0

我從1開始取整個層級。然後過濾出11 – SriniV

+0

啊,只是注意到它都在路徑中。所以我不得不提取那個領域並且用它做一些事情。 –