Oracle的層次查詢

 1 定義:
 
          層次查詢使用樹的遍歷,走遍含樹形結構的數據集合,來獲取樹的層次關係報表的方法
          樹形結構的父子關係,你能夠控制:
          ① 遍歷樹的方向,是自上而下,仍是自下而上
          ②  肯定層次的開始點(root)的位置
          層次查詢語句正是從這兩個方面來肯定的,start with肯定開始點,connect by肯定遍歷的方向  www.2cto.com  
 
          2 語法:

 
          註釋:
          ① level是僞列,表示等級
          ② from後面只能是一個表或視圖,對於from是視圖的,那麼這個view不能包含join
          ③ Where條件限制了查詢返回的行,可是不影響層次關係,屬於將節點截斷,可是這個被截斷的節點的下層child不受影響
          ④ prior是個形容詞,可放在任何地方
          ⑤ 完全剪枝條件應放在connect by;單點剪掉條件應放在where子句。可是,connect by的優先級要高於where,也就是sql引擎先執行connect by
          ⑥ 在start with中表達式能夠有子查詢,可是connect by中不能有子查詢
 
          3 遍歷樹:
 
          ㈠ Start with子句
          Start with肯定將哪行做爲root,若是沒有start with,則每行都看成root,而後查找其後代,這不是一個真實的查詢。Start with後面可使用子查詢或者任何合法的條件表達式
          例子:
[sql] 
select level,id,manager_id,last_name,title from s_emp  
      start with title=(select title from s_emp where manager_id is null)  
      connect by prior id=manager_id;  
 
          ㈡ Connect by子句
          Connect by與prior肯定一個層次查詢的條件和遍歷的方向(prior肯定)
          Connect by prior column_1=column_2;
          其中prior表示前一個節點的意思,能夠在connect by等號的先後,列以前,也能夠放到select中的列以前  www.2cto.com  
          Connect by也能夠帶多個條件,好比 connect by prior id=manager_id and id>10
 
                        1. )自頂向下遍歷:
                        先由根節點,而後遍歷子節點。column_1表示父key,column_2表示子key。即這種狀況下:connect by prior 父key=子key表示自頂向下,等同於connect by 子key=prior 父key.
                        例子:
[sql] 
select level,employee_id,manager_id,last_name,job_id from s_emp  
      start with manager_id=100  
      connect by  employee_id=prior manager_id;  
 
                         2. )自底向上遍歷:
                         先由最底層的子節點,遍歷一直找到根節點。與上面的相反。Connect by以後不能有子查詢,可是能夠加其餘條件,好比加上and id !=2等。這句話則會截斷樹枝,若是id=2的這個節點下面有不少子孫後代,則所有截斷不顯示。
                         例子:
[sql] 
select level,employee_id,manager_id,last_name,job_id from s_emp  
      start with manager_id=100    www.2cto.com  
      connect by prior employee_id=manager_id and employee_id<>120;  
 
          4 使用level和lpad格式化報表:
          Level是層次查詢的一個僞列,若是有level,必須有connect by,start with能夠沒有
          Lpad是在一個string的左邊添加必定長度的字符,而且知足中間的參數長度要求,不知足自動添加
          例子:
[sql] 
select level,employee_id,manager_id,lpad(last_name,length(last_name)+(level*4)-4,'_'),job_id from s_emp  
      start with manager_id=100  
      connect by prior employee_id=manager_id and employee_id<>120  
 
          5 修剪branches:
          where子句會將節點刪除,可是其後代不會受到影響,connect by 中加上條件會將知足條件的整個樹枝包括後代都刪除。要注意,若是是connect by以後加條件正好條件選到根,那麼結果和沒有加同樣
 
          6 實際應用
          1)查詢每一個等級上節點的數目
[sql] 
  先查看總共有幾個等級:  
select count(distinct level)  
 from s_emp  
 start with manager_id is null  
 connect by prior employee_id=manager_id  
  要查看每一個等級上有多少個節點,只要按等級分組,並統計節點的數目便可,能夠這樣寫:  
select level,count(last_name)  
 from s_emp  
 start with manager_id is null  
 connect by prior employee_id=manager_id  
 group by level    www.2cto.com  
 
          2)查看等級關係
          好比給定一個具體的員工看是否對某個員工有管理權
[sql] 
select level,a.* from   
s_emp a  
where first_name='Douglas' --被管理的節點  
start with manager_id is null --開始節點,即:根節點  
connect by prior employee_id=manager_id  
 
           3)刪除子樹
           好比有這樣的需求,如今要裁人,將某個部門的員工包括經理所有裁掉
           將id爲2的員工管理的全部員工包括本身刪除
[sql] 
delete from s_emp where employee_id in(  
elect employee_id from   
s_emp a  
start with employee_id=2 --從id=2的員工開始查找其子節點,把整棵樹刪除  
connect by prior employee_id=manager_id)  
 
           4)找出每一個部門的經理
[sql] 
select level,a.* from   
 s_emp a    www.2cto.com  
 start with manager_id is null  
 connect by prior employee_id=manager_id and department_id !=prior department_id;--當前行的dept_id不等於前一行的dept_id,即每一個子樹中選最高等級節點  
 
           5)查詢一個組織中最高的幾個等級
[sql] 
select level,a.* from   
 s_emp a  
  where level <=2 –查找前兩個等級  
 start with manager_id is null  
 connect by prior employee_id=manager_id and department_id !=prior department_id;  
 
       6)合計層次
          有兩個需求,一是對一個指定的子樹subtree作累加計算salary,一是將每行都做爲root節點,而後對屬於這個節點的全部子節點累加計算salary。
[sql] 
     第一種很簡單,求下sum就能夠了,語句:  
select sum(salary) from   
 s_emp a  
 start with id=2—好比從id=2開始  
 connect by prior id=manager_id;  
  
     第2個需求,須要用到第1個,對每一個root節點求這個樹的累加值,而後內部層次查詢的開始節點從外層查詢得到。  
select last_name,salary,(  
  select sum(salary) from   
 s_emp    www.2cto.com  
 start with id=a.id –讓每一個節點都成爲root  
 connect by prior id=manager_id) sumsalary  
 from s_emp a;  
 
           7)找出指定層次中的葉子節點
           Leaf(葉子)就是沒有子孫的孤立節點。 Oracle 10g提供了一個簡單的connect_by_isleaf=1,0表示非葉子節點
[sql] 
select level,id,manager_id,last_name, title from s_emp  
    where connect_by_isleaf=1 –表示查詢葉子節點  
      start with  manager_id=2  
      connect by prior id=manager_id;  
 
          7 10g新特性:
 
          ① 使用SIBLINGS關鍵字排序
             若是使用order by排序會破壞層次,在oracle10g中,增長了siblings關鍵字的排序
             語法:order  siblings  by <expre>
             它會保護層次,而且在每一個等級中按expre排序
             例子:
[sql] 
select level,    www.2cto.com  
       employee_id,last_name,manager_id  
       from s_emp  
       start with manager_id is null  
       connect by prior employee_id=manager_id  
       order siblings by last_name;  
 
          ② CONNECT_BY_ROOT
              Oracle10g新增connect_by_root,用在列名以前表示此行的根節點的相同列名的值
              例子:
[sql] 
select connect_by_root last_name root_last_name, connect_by_root employee_id root_id,  
      employee_id,last_name,manager_id  
      from s_emp  
      start with manager_id is null  
      connect by prior employee_id=manager_id  
相關文章
相關標籤/搜索