如果表中存在层次数据,则可以使用层次化查询子句查询出表中行记录之间的层次关系
基本语法:
START WITH <condition1> CONNECT BY [ NOCYCLE ] <condition2>
注: [ NOCYCLE ]参数暂时不解释
例:
SQL> select empno, ename, job, mgr, hiredate, sal, comm, deptno, level as lv from emp 2 start with empno = 7839 connect by (prior empno) = mgr; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO LV ----- ---------- ------------------------------ ----- ----------- --------- --------- ------ ---------- 7839 KING PRESIDENT 1981-11-17 5000.25 10 1 7566 JONES MANAGER 7839 1981-04-02 2975.25 20 2 7788 SCOTT ANALYST 7566 1982-12-09 3000.25 20 3 7876 ADAMS CLERK 7788 1983-01-12 1100.25 20 4 7902 FORD ANALYST 7566 1981-12-03 3000.25 20 3 7369 SMITH CLERK 7902 1980-12-17 800.25 20 4 7698 BLAKE MANAGER 7839 1981-05-01 2850.25 30 2 120 gxl SALESMAN 7698 2018-02-08 5500.25 300.00 10 3 7499 ALLEN SALESMAN 7698 1981-02-20 1600.25 300.00 30 3 7521 WARD SALESMAN 7698 1981-02-22 1250.25 500.00 30 3 7654 MARTIN SALESMAN 7698 1981-09-28 1250.25 1400.00 30 3 7844 TURNER SALESMAN 7698 1981-09-08 1500.25 0.00 30 3 7900 JAMES CLERK 7698 1981-12-03 950.25 30 3 7782 CLARK MANAGER 7839 1981-06-09 2450.25 10 2 7934 MILLER CLERK 7782 1982-01-23 1300.25 10 3 15 rows selected
表中存在层次数据
数据之间的层次关系即父子关系,通过表中列与列间的关系来描述,如EMP表中的EMPNO和MGR。EMPNO表示雇员编号,MGR表示领导
该雇员的人的编号,在表的每一行中都有一个表示父节点的MGR(除根节点外),通过每个节点的父节点,就可以确定整个树结构。
CONNECT BY [ NOCYCLE ] CONDITION2 层次子句作用
CONDITION2 [PRIOR expr = expr] : 指定层次结构中父节点与子节点之之间的关系。
CONDITION2 中的 一元运算符 PRIORY 必须放置在连接关系的两列中某一个的前面。在连接关系中,除了可以使用列名外,还允许使用列表达式。
SQL> select empno, ename, mgr, level as lv from emp start with mgr is null 2 connect by (prior empno) = mgr order by level; EMPNO ENAME MGR LV ----- ---------- ----- ---------- 7839 KING 1 7566 JONES 7839 2 7782 CLARK 7839 2 7698 BLAKE 7839 2 7902 FORD 7566 3 7521 WARD 7698 3 7788 SCOTT 7566 3 7900 JAMES 7698 3 120 gxl 7698 3 7499 ALLEN 7698 3 7934 MILLER 7782 3 7654 MARTIN 7698 3 7844 TURNER 7698 3 7876 ADAMS 7788 4 7369 SMITH 7902 4 15 rows selected
----分析
层次查询执行逻辑:
a. 确定上一行(相对于步骤b中的当前行),若start with 子句存在,则以该语句确定的行为上一行,若不存在则将所有的数据行视为上一行。
b. 从上一行出发,扫描除该行之外所有数据行。
c. 匹配条件 (prior empno) = mgr,注意 一元运算符 prior,意思是之前的,指上一行
当前行定义:步骤b中扫描得到的所有行中的某一行
匹配条件含义:当前行字段 mgr 的值等于上一行字段 empno中的值,若满足则取出该行,并将level + 1,
匹配完所有行记录后,将满足条件的行作为上一行,执行步骤 b,c。直到所有行匹配结束.
SQL> select empno, ename, mgr, level as lv from emp start with empno = 7876 2 connect by (prior mgr ) = empno order by level; EMPNO ENAME MGR LV ----- ---------- ----- ---------- 7876 ADAMS 7788 1 7788 SCOTT 7566 2 7566 JONES 7839 3 7839 KING 4
--分析
层次查询执行逻辑:
a .确定上一行(相对于步骤b中的当前行),若start with 子句存在,则以该语句确定的行为上一行,若不存在则将所有的数据行视为上一行。
b .从上一行出发,扫描除该行之外所有数据行。
c .匹配条件 (prior mgr ) = empno
注意 一元运算符 prior,意思是之前的,指上一行
当前行定义:步骤b中扫描得到的所有行中的某一行
匹配条件含义:当前行字段 empno 的值等于上一行字段 mgr 中的值,若满足则取出该行,并将
level + 1,
匹配完所有行记录后,将满足条件的行作为上一行,执行步骤 b,c。直到所有行匹配结束.
一、基本语法
SELECT * FROM TABLE START WITH <condition1> CONNECT BY [PRIOR] id= parentid;
层次查询(递归查询)用来查找存在父子关系的数据,也就是树形结构的数据;其返还的数据也能够明确的区分出每一层的数据。
"start with <condition>" -- 代表在这棵树中你要开始遍历的的节点,是用来限制第一层的数据,或者叫根节点数据;以这部分数据
为基础来查找第二层数据,然后以第二层数据查找第三层数据以此类推。
"connect by prior id = parentid" -- 标示节点之间的父子关系,是用来指明Oracle在查找数据时以怎样的一种关系去查找;比如说查
找第二层的数据时用第一层数据的id去跟表里面记录的parentid字段进行匹配,如果这个条件成立
那么查找出来的数据就是第二层数据,同理查找第三层第四层…等等都是按这样去匹配。
"level" -- 关键字,代表树形结构中的层级编号;第一层是数字1,第二层数字2,依次递增。
prior还有一种用法:
select * from table [start with condition1] connect by id= [prior] parentid
或者:
select * from table [start with condition1] connect by [prior] parentid = id
二、分层查询的例子
1.从根节点查找叶子节点,即从根节点自顶向下
SQL> select level rn , empno,mgr,substr(sys_connect_by_path(ename,'-->'),4) from emp 2 start with ename = 'KING' connect by prior empno = mgr; RN EMPNO MGR SUBSTR(SYS_CONNECT_BY_PATH(ENA ---------- ----- ----- -------------------------------------------------------------------------------- 1 7839 KING 2 7566 7839 KING-->JONES 3 7788 7566 KING-->JONES-->SCOTT 4 7876 7788 KING-->JONES-->SCOTT-->ADAMS 3 7902 7566 KING-->JONES-->FORD 4 7369 7902 KING-->JONES-->FORD-->SMITH 2 7698 7839 KING-->BLAKE 3 120 7698 KING-->BLAKE-->gxl 3 7499 7698 KING-->BLAKE-->ALLEN 3 7521 7698 KING-->BLAKE-->WARD 3 7654 7698 KING-->BLAKE-->MARTIN 3 7844 7698 KING-->BLAKE-->TURNER 3 7900 7698 KING-->BLAKE-->JAMES 2 7782 7839 KING-->CLARK 3 7934 7782 KING-->CLARK-->MILLER 15 rows selected
2.从叶子节点查找上层节点
SQL> select level rn , empno, mgr, substr(sys_connect_by_path(ename,'-->'),4) tb from emp 2 start with ename = 'ADAMS' connect by prior mgr = empno; RN EMPNO MGR TB ---------- ----- ----- -------------------------------------------------------------------------------- 1 7876 7788 ADAMS 2 7788 7566 ADAMS-->SCOTT 3 7566 7839 ADAMS-->SCOTT-->JONES 4 7839 ADAMS-->SCOTT-->JONES-->KING
三、sys_connect_by_path 递归函数
SYS_CONNECT_BY_PATH( cln, fmt ) :这个函数是oracle9i才新提出来的!它一定要和connect by子句合用!
第一个参数cln是形成树形式的字段,第二个参数fmt是父级和其子级分隔显示用的分隔符,
CONNECT BY PRIOR 是标示父子关系的对应!
SQL> SELECT level,empno,mgr,SYS_CONNECT_BY_PATH(ename, '>') pt 2 FROM emp START WITH ename = 'KING' CONNECT BY PRIOR empno = mgr; LEVEL EMPNO MGR PT ---------- ----- ----- -------------------------------------------------------------------------------- 1 7839 >KING 2 7566 7839 >KING>JONES 3 7788 7566 >KING>JONES>SCOTT 4 7876 7788 >KING>JONES>SCOTT>ADAMS 3 7902 7566 >KING>JONES>FORD 4 7369 7902 >KING>JONES>FORD>SMITH 2 7698 7839 >KING>BLAKE 3 120 7698 >KING>BLAKE>gxl 3 7499 7698 >KING>BLAKE>ALLEN 3 7521 7698 >KING>BLAKE>WARD 3 7654 7698 >KING>BLAKE>MARTIN 3 7844 7698 >KING>BLAKE>TURNER 3 7900 7698 >KING>BLAKE>JAMES 2 7782 7839 >KING>CLARK 3 7934 7782 >KING>CLARK>MILLER 15 rows selected