深入理解connect by
http://blog.oracle.com.cn/html/56/t-134656.html
開始學習connect by 的時候有很多的疑惑,在論壇里面拔了好多帖子,加上自己的理解。現整理如下,希望對一些人有所幫助。
connect by 一般用來生成樹狀結果集。對于scott schema 下的emp表中有empno,mgr這兩個字段,通過這兩個列能反應出雇員之間是領導與被領導的關系。
有些雇員領導一些人,有些雇員被領導同時又領導別人,有些雇員只被別人領導。雇員與雇員之間的關系就是一種樹結構。
我們先來看一個例子:
select rpad(' ',(level-1)*3)||ename from
emp
connect by prior empno = mgr
start with ename='KING';
RPAD('',(LEVEL-1)*3)||ENAME
----------------------------------------------------------------------------------------------------
KING
? ?JONES
? ?? ?SCOTT
? ?? ?? ?ADAMS
? ?? ?FORD
? ?? ?? ?SMITH
? ?BLAKE
? ?? ?ALLEN
? ?? ?WARD
? ?? ?MARTIN
? ?? ?TURNER
? ?? ?JAMES
? ?CLARK
? ?? ?MILLER
我們來分析一下結果集是怎樣生成的。
start with ename='KING'??子句表示以ename='KING'這行記錄開始,我們首先定位到這一行。
select * from emp where ename='KING';
? ???EMPNO ENAME? ?? ?JOB? ?? ?? ?? ???MGR HIREDATE? ?? ?? ?SAL? ?? ? COMM? ???DEPTNO
---------- ---------- --------- ---------- --------- ---------- ---------- ----------
? ?? ?7839 KING? ?? ? PRESIDENT? ?? ?? ?? ?17-NOV-81? ?? ? 5000? ?? ?? ?? ?? ?? ???10
然后按照connect by prior empno = mgr定義的規則去查找子節點。
connect by prior empno = mgr 這個子句描述了通過字段empno,mgr來確立雇員之間的領導關系。
至于prior關鍵字放在那個字段前面,意義完全不同,prior 放在哪個字段前面,表示以這個字段為父字段,另一個為子字段。
KING 父字段 empno=7839,那么哪些人是KING的直接下屬呢?即滿足如下條件的人
select ename from emp where mgr = 7839;
ENAME
----------
JONES
BLAKE
CLARK
然后再按照此規則循環下去。
我們想想如果給出的條件是
connect by??empno = prior mgr
start with ename='KING';
結果是什么樣的呢?
同樣先定位到ename=’KING‘這一條記錄,父字段 mgr = null ,那么哪些人是KING的直接下屬呢?即滿足如下條件的人
scott@ORCL> select ename from emp where empno is null ;
no rows selected
所以按照connect by empno = prior mgr這種規則KING沒有下屬 。
我們來驗證一下
select rpad(' ',(level-1)*3)||ename from
emp
connect by empno = prior mgr
start with ename='KING';
RPAD('',(LEVEL-1)*3)||ENAME
----------------------------------------------------------------------------------------------------
KING
提醒一下connect by empno = prior mgr 與 connect by prior mgr = empno 效果相同。
所以得出如下結論:定位一條記錄后,取出父字段的值X ,通過如下方法查找其子節點
select * from table_name where 子字段=X ;
level表示的是每行記錄的層數,根節點為1,直接子節點為2,子子節點為3 ,依此類推。
請看如下查詢:
col e_name for a30
select level,rpad(' ',(level-1)*3)||ename e_name from
emp
connect by prior empno = mgr
start with ename='KING';
? ???LEVEL E_NAME
---------- ------------------------------
? ?? ?? ?1 KING
? ?? ?? ?2? ? JONES
? ?? ?? ?3? ?? ? SCOTT
? ?? ?? ?4? ?? ?? ? ADAMS
? ?? ?? ?3? ?? ? FORD
? ?? ?? ?4? ?? ?? ? SMITH
? ?? ?? ?2? ? BLAKE
? ?? ?? ?3? ?? ? ALLEN
? ?? ?? ?3? ?? ? WARD
? ?? ?? ?3? ?? ? MARTIN
? ?? ?? ?3? ?? ? TURNER
? ?? ?? ?3? ?? ? JAMES
? ?? ?? ?2? ? CLARK
? ?? ?? ?3? ?? ? MILLER
二、節點和分支的裁剪
在對樹結構進行查詢時,可以去掉表中的某些行,也可以剪掉樹中的一個分支,使用WHERE子句來限定樹型結構中的單個節點,以去掉樹中的單個節點,但它卻不影響其后代節
點。
col e_name for a30
select rpad(' ',LEVEL*3) ||ENAME e_name
FROM EMP
WHERE ename!='SCOTT'
CONNECT BY PRIOR empno = mgr
START WITH ENAME='KING';
E_NAME
------------------------------
? ?KING
? ?? ?JONES
? ?? ?? ?? ?ADAMS
? ?? ?? ?FORD
? ?? ?? ?? ?SMITH
? ?? ?BLAKE
? ?? ?? ?ALLEN
? ?? ?? ?WARD
? ?? ?? ?MARTIN
? ?? ?? ?TURNER
? ?? ?? ?JAMES
? ?? ?CLARK
? ?? ?? ?MILLER
13 rows selected.
在這個查詢中,僅剪去了樹中單個節點SCOTT。若希望剪去樹結構中的某個分支,則要用CONNECT BY 子句。CONNECT BY 子句是限定樹型結構中的整個分支,既要剪除分支
上的單個節點,也要剪除其后代節點。
例如顯示KING領導下的全體雇員信息,除去SCOTT領導的一支。
select rpad(' ',LEVEL*3) ||ENAME e_name
FROM EMP
CONNECT BY PRIOR empno = mgr and ename!='SCOTT'
START WITH ENAME='KING';
E_NAME
------------------------------
? ?KING
? ?? ?JONES
? ?? ?? ?FORD
? ?? ?? ?? ?SMITH
? ?? ?BLAKE
? ?? ?? ?ALLEN
? ?? ?? ?WARD
? ?? ?? ?MARTIN
? ?? ?? ?TURNER
? ?? ?? ?JAMES
? ?? ?CLARK
? ?? ?? ?MILLER
12 rows selected.
這個查詢結果就與上個不同,除了剪去單個節點SCOTT外,還將SCOTT的子節點ADAMS剪掉,即把SCOTT這個分支剪掉了。
當然WHERE子句可以和CONNECT BY子句聯合使用,這樣能夠同時剪掉單個節點和樹中的某個分支。
三,其實connect by 還有另外一種功能,可以用來生成序列。
如:
select level id from dual
connect by level<=10;
? ?? ???ID
----------
? ?? ?? ?1
? ?? ?? ?2
? ?? ?? ?3
? ?? ?? ?4
? ?? ?? ?5
? ?? ?? ?6
? ?? ?? ?7
? ?? ?? ?8
? ?? ?? ?9
? ?? ???10
10 rows selected.
我們來分析一下其工作原理 ,level<=10用來控制循環的次數,即要重復多少次掃描表dual中的內容。第一次掃描得出的結果集的level都是1,第二次掃描的結果集的level都是2,依此類推。可能用文字描述的不太容易懂,下面我們通過試驗來說明:
scott@ORCL> create table test as select ename from emp where rownum<=2;
Table created.
scott@ORCL> select level,ename from test connect by level<=2;
? ???LEVEL ENAME
---------- ----------
? ?? ?? ?1 SMITH
? ?? ?? ?2 SMITH
? ?? ?? ?2 ALLEN
? ?? ?? ?1 ALLEN
? ?? ?? ?2 SMITH
? ?? ?? ?2 ALLEN
6 rows selected.
scott@ORCL>??select level,ename from test connect by level<=3;
? ???LEVEL ENAME
---------- ----------
? ?? ?? ?1 SMITH
? ?? ?? ?2 SMITH
? ?? ?? ?3 SMITH
? ?? ?? ?3 ALLEN
? ?? ?? ?2 ALLEN
? ?? ?? ?3 SMITH
? ?? ?? ?3 ALLEN
? ?? ?? ?1 ALLEN
? ?? ?? ?2 SMITH
? ?? ?? ?3 SMITH
? ?? ?? ?3 ALLEN
? ?? ?? ?2 ALLEN
? ?? ?? ?3 SMITH
? ?? ?? ?3 ALLEN
14 rows selected.
對比一下上面的結果集,我們就能理解這種用法的原理了。
總結
以上是生活随笔為你收集整理的深入理解connect by的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java解压gz文件
- 下一篇: Nutch 入门