本博客是自己在學習和工作途中的積累與總結,僅供自己參考,也歡迎大家轉載,轉載時請注明出處。
http://www.cnblogs.com/king-xg/p/6927541.html
如果覺得對您有幫助,請點擊推薦或收藏本博客,謝謝。
1. 使用了connect by 的人,大多會存在一些疑問:
a. start with 后接的節點不同導致查詢的方向(上或下)不同?
b. prior 關鍵字理解?
c. 突然出現的諸多冗余數據是怎么來的?
案例數據集就拿我上一篇博客的案例表來用了(刪掉了循環列)
樹形展示圖:
問題解答:
答: 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 關鍵字時
講解:
問題-向上查詢的兩種特殊情況:
向下查詢且后接子節點列與向下查詢且后接父節點列查詢的結果集:
select emp_id,lead_id,emp_name,prior emp_name as lead_name,salary from employee start with emp_id=1 connect by prior emp_id = lead_id ;
select emp_id,lead_id,emp_name,prior emp_name as lead_name,salary from employee start with lead_id=1 connect by prior emp_id = lead_id ;
少了一行記起始記錄,當然也可以使結果集不缺少記錄,前提是其實行需定位到同一行
select emp_id,lead_id,emp_name,prior emp_name as lead_name,salary from employee start with lead_id=0 connect by prior emp_id = lead_id ;
解釋: lead_id=0和emp_id=1指向的是同一行
問題-冗余數據的產生情況:
(1). 向上查詢且后接父節點列時
select emp_id,lead_id,emp_name as lead_name,prior emp_name as emp_name,salary from employee start with lead_id=2 connect by emp_id = prior lead_id order by lead_id;
多了兩條冗余記錄,其實根據數據不難看出冗余的是起始節點記錄的所有父節點和祖先節點的記錄行
畫圖分析:
所以一般不建議向上查詢時start with后接父節點列,這樣會造成很多冗余數據行,拖慢了查詢速度。
強烈建議: 需要查詢父節點行或祖先記錄行時,可以用向上查詢且后接子節點列
舉例:
select emp_id,lead_id,emp_name as lead_name,prior emp_name as emp_name,salary from employee start with emp_id=2 connect by emp_id = prior lead_id order by lead_id;
(2). sql語句中不包含start with 關鍵字時,同樣也會產生冗余數據行,而且比上面的更多原因就在下面:
舉例:
select emp_id,lead_id,emp_name,prior emp_name as lead_name,salary from employee connect by prior emp_id = lead_id
產生了10條冗余數據行,為什么呢?
其實很簡單,由於缺少start with 指定起始行,那么oracle會根據proir修飾的字段進行一個內部的動態指定起始行位置,規則是由上至下,由左至右。
首先,指定起始節點為根節點(king),向下查詢,然后指定子節點之一(jack)為起始節點,再向下查詢,然后指定子節點之一(arise)為起始節點,再向下查詢,....循環往復,直到到達最右側最下方的葉子節點為止。
這里大家可能就會想,為什么是向下查詢,而不是向上呢,原因就在於proir 的為止或者說他所修飾的列是子節點列還是父節點列有關,翻譯一下就是"以子節點列為匹配條件,查詢父節點",這么一看知道是向下查詢嘍。
同理,connect by emp_id = prior lead_id 這個表示向上查詢,其他同理~_~