深入理解connect by
http://blog.oracle.com.cn/html/56/t-134656.html
開始學(xué)習(xí)connect by 的時(shí)候有很多的疑惑,在論壇里面拔了好多帖子,加上自己的理解。現(xiàn)整理如下,希望對(duì)一些人有所幫助。
connect by 一般用來(lái)生成樹狀結(jié)果集。對(duì)于scott schema 下的emp表中有empno,mgr這兩個(gè)字段,通過(guò)這兩個(gè)列能反應(yīng)出雇員之間是領(lǐng)導(dǎo)與被領(lǐng)導(dǎo)的關(guān)系。
有些雇員領(lǐng)導(dǎo)一些人,有些雇員被領(lǐng)導(dǎo)同時(shí)又領(lǐng)導(dǎo)別人,有些雇員只被別人領(lǐng)導(dǎo)。雇員與雇員之間的關(guān)系就是一種樹結(jié)構(gòu)。
我們先來(lái)看一個(gè)例子:
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
我們來(lái)分析一下結(jié)果集是怎樣生成的。
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定義的規(guī)則去查找子節(jié)點(diǎn)。
connect by prior empno = mgr 這個(gè)子句描述了通過(guò)字段empno,mgr來(lái)確立雇員之間的領(lǐng)導(dǎo)關(guān)系。
至于prior關(guān)鍵字放在那個(gè)字段前面,意義完全不同,prior 放在哪個(gè)字段前面,表示以這個(gè)字段為父字段,另一個(gè)為子字段。
KING 父字段 empno=7839,那么哪些人是KING的直接下屬呢?即滿足如下條件的人
select ename from emp where mgr = 7839;
ENAME
----------
JONES
BLAKE
CLARK
然后再按照此規(guī)則循環(huán)下去。
我們想想如果給出的條件是
connect by??empno = prior mgr
start with ename='KING';
結(jié)果是什么樣的呢?
同樣先定位到ename=’KING‘這一條記錄,父字段 mgr = null ,那么哪些人是KING的直接下屬呢?即滿足如下條件的人
scott@ORCL> select ename from emp where empno is null ;
no rows selected
所以按照connect by empno = prior mgr這種規(guī)則KING沒(méi)有下屬 。
我們來(lái)驗(yàn)證一下
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 效果相同。
所以得出如下結(jié)論:定位一條記錄后,取出父字段的值X ,通過(guò)如下方法查找其子節(jié)點(diǎn)
select * from table_name where 子字段=X ;
level表示的是每行記錄的層數(shù),根節(jié)點(diǎn)為1,直接子節(jié)點(diǎn)為2,子子節(jié)點(diǎn)為3 ,依此類推。
請(qǐng)看如下查詢:
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
二、節(jié)點(diǎn)和分支的裁剪
在對(duì)樹結(jié)構(gòu)進(jìn)行查詢時(shí),可以去掉表中的某些行,也可以剪掉樹中的一個(gè)分支,使用WHERE子句來(lái)限定樹型結(jié)構(gòu)中的單個(gè)節(jié)點(diǎn),以去掉樹中的單個(gè)節(jié)點(diǎn),但它卻不影響其后代節(jié)
點(diǎn)。
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.
在這個(gè)查詢中,僅剪去了樹中單個(gè)節(jié)點(diǎn)SCOTT。若希望剪去樹結(jié)構(gòu)中的某個(gè)分支,則要用CONNECT BY 子句。CONNECT BY 子句是限定樹型結(jié)構(gòu)中的整個(gè)分支,既要剪除分支
上的單個(gè)節(jié)點(diǎn),也要剪除其后代節(jié)點(diǎn)。
例如顯示KING領(lǐng)導(dǎo)下的全體雇員信息,除去SCOTT領(lǐng)導(dǎo)的一支。
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.
這個(gè)查詢結(jié)果就與上個(gè)不同,除了剪去單個(gè)節(jié)點(diǎn)SCOTT外,還將SCOTT的子節(jié)點(diǎn)ADAMS剪掉,即把SCOTT這個(gè)分支剪掉了。
當(dāng)然WHERE子句可以和CONNECT BY子句聯(lián)合使用,這樣能夠同時(shí)剪掉單個(gè)節(jié)點(diǎn)和樹中的某個(gè)分支。
三,其實(shí)connect by 還有另外一種功能,可以用來(lái)生成序列。
如:
select level id from dual
connect by level<=10;
? ?? ???ID
----------
? ?? ?? ?1
? ?? ?? ?2
? ?? ?? ?3
? ?? ?? ?4
? ?? ?? ?5
? ?? ?? ?6
? ?? ?? ?7
? ?? ?? ?8
? ?? ?? ?9
? ?? ???10
10 rows selected.
我們來(lái)分析一下其工作原理 ,level<=10用來(lái)控制循環(huán)的次數(shù),即要重復(fù)多少次掃描表dual中的內(nèi)容。第一次掃描得出的結(jié)果集的level都是1,第二次掃描的結(jié)果集的level都是2,依此類推。可能用文字描述的不太容易懂,下面我們通過(guò)試驗(yàn)來(lái)說(shuō)明:
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.
對(duì)比一下上面的結(jié)果集,我們就能理解這種用法的原理了。
總結(jié)
以上是生活随笔為你收集整理的深入理解connect by的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java解压gz文件
- 下一篇: Nutch 入门