1. 程式人生 > >08.SQL基礎-->層次化查詢(START BY ... CONNECT BY PRIOR)

08.SQL基礎-->層次化查詢(START BY ... CONNECT BY PRIOR)

log ada body 偽列 過濾 exp image 遍歷 col

SQL基礎-->層次化查詢(START BY ... CONNECT BY PRIOR)

層次化查詢,即樹型結構查詢,是SQL中經常用到的功能之一,通常由根節點,父節點,子節點,葉節點組成,其語法如下:

   SELECT [LEVEL] ,column,expression,...
   FROM table_name
   [WHERE where_clause]
   [[START WITH start_condition] [CONNECT BY PRIOR prior_condition]];
  
   LEVEL:為偽列,用於表示樹的層次
   start_condition:層次化查詢的起始條件

--使用start with ...connect by prior 從根節點開始遍歷

select empno,mgr,ename,job from emp
start with empno = 7839
connect by prior empno = mgr;

技術分享圖片

樹型結構遍歷過程(通過上面的查詢來描述)
  1).從根節點開始(即where_clause中的條件,如果為非根節點則分根節點作為根節點開始遍歷,如上例empno = 7839)
  2).遍歷根節點(得到empno = 7839記錄的相關信息)
  3).判斷該節點是否存在由子節點,如果則訪問最左側未被訪問的子節點,轉到),否則下一步
    如上例中prior_condition為empno = mgr,即子節點的mgr等於父節點的empno,在此時mgr為7839的記錄
  4).當節點為葉節點,則訪問完畢,否則,轉到)
  5).返回到該節點的父節點,轉到)
 
--偽列level的使用
--註意connect by prior empno = mgr 的理解
--prior表示前一條記錄,即下一條返回記錄的mgr應當等於前一條記錄的empno

  

select level,empno,mgr,ename,job from emp
start with ename = ‘KING‘
connect by prior empno = mgr
order by level;

技術分享圖片

--獲得層次數

select count(distinct level) "Level" from emp
start with ename = ‘KING‘
connect by prior empno = mgr;

技術分享圖片

--格式化層次查詢結果(使用左填充* level - 1個空格)

col Ename for a30
select
level, lpad( ,2 * level - 1) || ename as "Ename", job from emp start with ename = KING connect by prior empno = mgr;

技術分享圖片

--從非根節點開始遍歷(只需修改start with 中的條件即可)

select level,
  lpad(‘ ‘,2 * level - 1) || ename as "Ename",
  job
from emp
start with ename = ‘SCOTT‘
connect by prior empno = mgr;

技術分享圖片

--從下向上遍歷(交換connect by prior中的條件即可,使用mgr = empno)
--註意connect by prior mgr = empno 的理解
--prior表示前一條記錄,即下一條返回記錄的empno應當等於前一條記錄的mgr
select level,
  lpad(‘ ‘,2 * level - 1) || ename as "Ename",
  job
from emp
start with ename = ‘SCOTT‘
connect by prior mgr = empno; 

技術分享圖片

--從下向上遍歷(也可以將prior置於等號右邊,得到相同的結果)

select level,
  lpad(‘ ‘,2 * level - 1) || ename as "Ename",
  job
from emp
start with ename = ‘SCOTT‘
connect by empno = prior mgr;

技術分享圖片

--從層次查詢中刪除節點和分支

select level,
  lpad(‘ ‘,2 * level - 1) || ename as "Ename"
  ,job
from emp
where ename != ‘SCOTT‘  --通過where子句來過濾SCOTT用戶,但SCOTT的下屬ADAMS並沒有過濾掉
start with empno = 7839   
connect by prior empno = mgr;

技術分享圖片

--通過將過濾條件由where 子句的內容移動到connect by prior 子句中過濾掉SCOTT及其下屬

select level,
  lpad( ,2 * level - 1) || ename as "Ename"
  ,job
from emp
start with empno = 7839
connect by prior empno = mgr and ename != SCOTT;

技術分享圖片

--在層次化查詢中增加過濾條件或使用子查詢

select level,
  lpad(‘ ‘,2 * level - 1) || ename as "Ename"
  ,job
from emp
where sal > 2500
start with empno = 7839
connect by prior empno = mgr;

技術分享圖片

select level,
  lpad(‘ ‘,2 * level - 1) || ename as "Ename"
  ,job
from emp
where sal > (select avg(sal) from emp)
start with empno = 7839
connect by prior empno = mgr ;

技術分享圖片

08.SQL基礎-->層次化查詢(START BY ... CONNECT BY PRIOR)