1. 程式人生 > >Oracle的start with connect by prior 遞迴查詢

Oracle的start with connect by prior 遞迴查詢

這個子句主要是用於B樹結構型別的資料遞迴查詢,給出B樹結構型別中的任意一個結點,遍歷其最終父結點或者子結點。

建立測試表:

create table a_test
( parentid varchar2(10),
  subid    varchar2(10));

insert into a_test values ( '1', '2' );
insert into a_test values ( '1', '3' );
insert into a_test values ( '2', '4' );
insert into a_test values ( '2', '5' );
insert into a_test values ( '3', '6' );
insert into a_test values ( '3', '7' );
insert into a_test values ( '5', '8' );
insert into a_test values ( '5', '9' );
insert into a_test values ( '7', '10' );
insert into a_test values ( '7', '11' );
insert into a_test values ( '10', '12' );
insert into a_test values ( '10', '13' );

commit;

select * from a_test;

結果如下:

對應B樹結構為:

先介紹相關命令含義:

start with 子句:遍歷起始條件,有個小技巧,如果要查父結點,這裡可以用子結點的列,反之亦然。

connect by 子句:連線條件。關鍵詞prior,prior跟父節點列parentid放在一起,就是往父結點方向遍歷;prior跟子結點列subid放在一起,則往葉子結點方向遍歷,parentid、subid兩列誰放在“=”前都無所謂,關鍵是prior跟誰在一起。

order by 子句:排序。

舉例1:

--父節點遍歷
select t.parentid, t.subid, level
  from a_test t
 start with t.subid = '7'
connect by subid = prior parentid
 order by level desc;

結果如下:

舉例2:

--父節點遍歷
select t.parentid,t.subid,level
from a_test t
start with t.parentid = '7'
connect by prior subid = parentid
order by level desc;

查詢結果如下:

關於start with子句中選擇不同的列的區別:

原意是要以7為父結點,遍歷其子結點,左圖取的是父結點列的值,結果符合原意;右圖取的是子結點列的值,結果多餘的顯示了7 的父結點3。

結果可看出多出了2條冗餘資料,均為長輩節點:

分析如下:(建議: 需要查詢父節點行或祖先記錄行時,可以用向上查詢且後接子節點列

)

注意事項:

1. start with 僅僅只是指定從那個節點開始,並不是上下查詢的判斷

2. start with 在向下查詢時,僅有一點不同,後接子節點列則查詢會比後接父節點列多一條記錄,多出來的一條記錄就是起始節點列,即,後接子節點列會查出起始行,後接父節點列則不會查詢出起始行

3. 只有connect by語句中的prior關鍵字的位置決定了上下查詢的方向,補充一下,如何判斷上下查詢

   (a). 死記 prior 子節點列 = 父節點列 [向下查詢],prior 父節點列 = 子節點列 [向上查詢]

   (b). 另一種更方便一點,“prior 子節點列 = 父節點列 [向下查詢]”  就把proir 翻譯成"以...為查詢條件",那麼就是這樣翻譯的"以子節點列為查詢條件,查詢父節點列",舉例:"prior emp_id = lead_id" 翻譯之後就是"以emp_id為查詢條件查詢lead_id",即向下查詢,這樣理解起來是不是感覺很簡單了;

4. 向上查詢的兩種特殊情況,(1). 後接子節點列   (2). 後接父節點列

5.多出的冗餘資料會在如下情況中出現

 (a). 向上查詢且start with 後接父節點列時     (b). sql語句中不包含start with 關鍵字時