层次化查询(START BY ... CONNECT BY PRIOR)
注:本文整理自网络。
一、概述
层次化查询,即树型结构查询,是SQL中经常用到的功能之一,通常由根节点,父节点,子节点,叶节点组成。
二、主要内容
1.语法结构:
SELECT
[LEVEL] ,columnname...
FROM table_name
[WHERE where_clause]
[[START WITH start_condition]
[CONNECT BY PRIOR prior_condition]];
参数说明:
LEVEL:
为伪列,用于表示树的层次。
start_condition:层次化查询起始条件。
prior_condition:定义父节点和子节点之间的关系。
2.使用说明
(1).使用start with...connect by prior
从根节点开始遍历.
SQL> select level,empno,mgr,ename from emp
start with empno = 7839
connect by prior empno = mgr
order by level;
结果如下:
LEVEL EMPNO
MGR ENAME
------- ----- ----- -------
1
7839
KING
2 7566 7839 JONES
2 7698 7839 BLAKE
2 7782 7839 CLARK
3 7902 7566 FORD
3 7521 7698 WARD
3 7900 7698 JAMES
3 7934 7782 MILLER
3 7499 7698 ALLEN
3 7788 7566 SCOTT
3 7654 7698 MARTIN
3 7844 7698 TURNER
4 7876 7788 ADAMS
4 7369 7902 SMITH
注:connect by prior empno =
mgr表示前一条记录的empno是这条记录的mgr,即从顶至下的查询。
(2).获得层次数
SQL>
select count(distinct level) "Level" from emp
start with ename = 'KING'
connect by prior empno = mgr;
Level
-------
4
(3).格式化层次查询结果(使用左填充* level - 1个空格)
SQL>
col Ename for a30--指定输出格式,ENAME指定30个字符,多余的显示至下一行。
SQL>
select level,lpad(' ',2 * level - 1) || ename as "Ename" from
emp
start with ename = 'KING'
connect by prior empno = mgr;
结果如下:
LEVEL
Ename
---------- ---------------
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
(4).从非根节点开始遍历(只需修改start with
中的条件即可)
SQL>
select level,
lpad(' ',2 * level - 1) || ename as "Ename" from emp
start with ename = 'SCOTT'
connect by prior empno = mgr;
结果如下:
LEVEL Ename
---------- ------------------------------
1 SCOTT
2 ADAMS
(5).从下向上遍历(交换connect by prior中的条件即可,使用mgr
= empno)
注意connect by prior mgr = empno 的理解
prior表示前一条记录,即下一条返回记录的empno应当等于前一条记录的mgr
SQL>
select level,
lpad(' ',2 * level - 1) || ename as "Ename" from emp
start with ename = 'SCOTT'
connect by prior mgr = empno;
--从下向上遍历(也可以将prior置于等号右边,得到相同的结果)
SQL>
select level,
lpad(' ',2 * level - 1) || ename as "Ename" from emp
start with ename = 'SCOTT'
connect by empno = prior mgr;
(6).从层次查询中删除节点和分支
SQL>
select level,
lpad(' ',2 * level - 1) || ename as "Ename"
from emp
where ename !=
'SCOTT'
--通过where子句来过滤SCOTT用户,但SCOTT的下属ADAMS并没有过滤掉
start with empno =
7839
connect by prior empno = mgr;
--通过将过滤条件由where 子句的内容移动到connect by prior
子句中过滤掉SCOTT及其下属
SQL>
select level,
lpad(' ',2 * level - 1) || ename as "Ename" from emp
start with empno = 7839
connect by prior empno = mgr and ename != 'SCOTT';