层次查询是一种确定数据行间关系的一种操作手段。层次查询遍历的是一个树形结构。基本语法如下,以下语法嵌入到标准SQL中即可达到层次查询的目的:

level,... ...【注释:伪列,用于select子句中,根据数据所处的层次结构自动层次编号】

connect by [nocycle] prior 连接条件 【注释:指定数据之间的连接,其中nocycle需要结合connect_by_iscycle伪列确定出父子节点循环关系,不指定prior则仅显示第一层数据】

[start with 开始条件] 【注释:根节点开始条件】

一、测试数据

测试表依旧采用Oracle经典的scott模式下的emp表,结构如下:

EMP:

create table EMP

(

EMPNO    NUMBER(4) not null,

ENAME    VARCHAR2(10),

JOB      VARCHAR2(9),

MGR      NUMBER(4),

HIREDATE DATE,

SAL      NUMBER(7,2),

COMM     NUMBER(7,2),

DEPTNO   NUMBER(2),

SEX      VARCHAR2(2) default '男'

)

-- Create/Recreate primary, unique and foreign key constraints

alter table EMP

add constraint PK_EMP primary key (EMPNO)

using index;

alter table EMP

add constraint FK_DEPTNO foreign key (DEPTNO)

references DEPT (DEPTNO);

SQL> select * from emp;

EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO SEX

----- ---------- --------- ----- ----------- --------- --------- ------ ---

7369 SMITH      CLERK      7902 1980/12/17     800.00               20 男

7499 ALLEN      SALESMAN   7698 1981/2/20     1600.00    300.00     30 女

7521 WARD       SALESMAN   7698 1981/2/22     1250.00    500.00     30 女

7566 JONES      MANAGER    7839 1981/4/2      2975.00               20 女

7654 MARTIN     SALESMAN   7698 1981/9/28     1250.00   1400.00     30 女

7698 BLAKE      MANAGER    7839 1981/5/1      2850.00               30 女

7782 CLARK      MANAGER    7839 1981/6/9      2450.00               10 女

7788 SCOTT      ANALYST    7566 1987/4/19     3000.00               20 男

7839 KING       PRESIDENT       1981/11/17    5000.00               10 女

7844 TURNER     SALESMAN   7698 1981/9/8      1500.00      0.00     30 女

7876 ADAMS      CLERK      7788 1987/5/23     1100.00               20 男

7900 JAMES      CLERK      7698 1981/12/3      950.00               30 女

7902 FORD       ANALYST    7566 1981/12/3     3000.00               20 女

7934 MILLER     CLERK      7782 1982/1/23     1300.00               10 男

14 rows selected

二、层次查询示例

例:查询员工及其员工领导关系:

SQL> select empno, level, lpad('|-', level * 2, ' ') || ename as empname, mgr

2    from emp

3  connect by prior empno = mgr

4   start with mgr is null;

EMPNO      LEVEL EMPNAME                          MGR

----- ---------- ------------------------------ -----

7839          1 |-KING

7566          2   |-JONES                       7839

7788          3     |-SCOTT                     7566

7876          4       |-ADAMS                   7788

7902          3     |-FORD                      7566

7369          4       |-SMITH                   7902

7698          2   |-BLAKE                       7839

7499          3     |-ALLEN                     7698

7521          3     |-WARD                      7698

7654          3     |-MARTIN                    7698

7844          3     |-TURNER                    7698

7900          3     |-JAMES                     7698

7782          2   |-CLARK                       7839

7934          3     |-MILLER                    7782

14 rows selected

1、connect_by_isleaf

在一个树形结构中,节点分为根节点和叶子节点两种,用户可以通过connect_by_isleaf伪列判断一个节点是根节点还是叶子节点,如果返回值为0,则表示根节点,返回1则表示叶子节点。

SQL> select empno,

2         level,

3         lpad('|-', level * 2, ' ') || ename as empname,

4         mgr,

5         decode(connect_by_isleaf, 0, '根节点', 1, '    叶子节点') as isleaf

6    from emp

7  connect by prior empno = mgr

8   start with mgr is null;

EMPNO      LEVEL EMPNAME                          MGR ISLEAF

----- ---------- ------------------------------ ----- ------------

7839          1 |-KING                               根节点

7566          2   |-JONES                       7839 根节点

7788          3     |-SCOTT                     7566 根节点

7876          4       |-ADAMS                   7788     叶子节点

7902          3     |-FORD                      7566 根节点

7369          4       |-SMITH                   7902     叶子节点

7698          2   |-BLAKE                       7839 根节点

7499          3     |-ALLEN                     7698     叶子节点

7521          3     |-WARD                      7698     叶子节点

7654          3     |-MARTIN                    7698     叶子节点

7844          3     |-TURNER                    7698     叶子节点

7900          3     |-JAMES                     7698     叶子节点

7782          2   |-CLARK                       7839 根节点

7934          3     |-MILLER                    7782     叶子节点

14 rows selected

2、connect_by_root

取得某一字段在本层次中根节点的数据名称。

使用方法:connect_by_root 字段名称 [as 别名].

SQL> select empno,

2         level,

3         lpad('|-', level * 2, ' ') || ename as empname,

4         mgr,

5         decode(connect_by_isleaf, 0, '根节点', 1, '    叶子节点') as isleaf,

6         connect_by_root ename as rootname

7    from emp

8  connect by prior empno = mgr

9   start with mgr is null;

EMPNO      LEVEL EMPNAME                          MGR ISLEAF       ROOTNAME

----- ---------- ------------------------------ ----- ------------ ----------

7839          1 |-KING                               根节点       KING

7566          2   |-JONES                       7839 根节点       KING

7788          3     |-SCOTT                     7566 根节点       KING

7876          4       |-ADAMS                   7788     叶子节点 KING

7902          3     |-FORD                      7566 根节点       KING

7369          4       |-SMITH                   7902     叶子节点 KING

7698          2   |-BLAKE                       7839 根节点       KING

7499          3     |-ALLEN                     7698     叶子节点 KING

7521          3     |-WARD                      7698     叶子节点 KING

7654          3     |-MARTIN                    7698     叶子节点 KING

7844          3     |-TURNER                    7698     叶子节点 KING

7900          3     |-JAMES                     7698     叶子节点 KING

7782          2   |-CLARK                       7839 根节点       KING

7934          3     |-MILLER                    7782     叶子节点 KING

14 rows selected

3、sys_connect_by_path(column,char)

该函数根据层次节点关系,自动地将当前根节点中所有相关路径进行显示。

SQL> select empno,

2         level,

3         lpad('|=', level * 2, ' ') || sys_connect_by_path(ename, ' -> ') as empname,

4         mgr,

5         decode(connect_by_isleaf, 0, '根节点', 1, '    叶子节点') as isleaf,

6         connect_by_root ename as rootname

7    from emp

8  connect by prior empno = mgr

9   start with mgr is null;

EMPNO      LEVEL EMPNAME                                              MGR ISLEAF       ROOTNAME

----- ---------- -------------------------------------------------- ----- ------------ ----------

7839          1 |= -> KING                                               根节点       KING

7566          2   |= -> KING -> JONES                               7839 根节点       KING

7788          3     |= -> KING -> JONES -> SCOTT                    7566 根节点       KING

7876          4       |= -> KING -> JONES -> SCOTT -> ADAMS         7788     叶子节点 KING

7902          3     |= -> KING -> JONES -> FORD                     7566 根节点       KING

7369          4       |= -> KING -> JONES -> FORD -> SMITH          7902     叶子节点 KING

7698          2   |= -> KING -> BLAKE                               7839 根节点       KING

7499          3     |= -> KING -> BLAKE -> ALLEN                    7698     叶子节点 KING

7521          3     |= -> KING -> BLAKE -> WARD                     7698     叶子节点 KING

7654          3     |= -> KING -> BLAKE -> MARTIN                   7698     叶子节点 KING

7844          3     |= -> KING -> BLAKE -> TURNER                   7698     叶子节点 KING

7900          3     |= -> KING -> BLAKE -> JAMES                    7698     叶子节点 KING

7782          2   |= -> KING -> CLARK                               7839 根节点       KING

7934          3     |= -> KING -> CLARK -> MILLER                   7782     叶子节点 KING

14 rows selected

SQL> select empno,

2         level,

3         lpad('|=', level * 2, ' ') || sys_connect_by_path(ename, ' -> ') as empname,

4         mgr,

5         decode(connect_by_isleaf, 0, '根节点', 1, '    叶子节点') as isleaf,

6         connect_by_root ename as rootname

7    from emp

8  connect by prior empno = mgr

9         and empno != 7698

10   start with mgr is null;

EMPNO      LEVEL EMPNAME                                              MGR ISLEAF       ROOTNAME

----- ---------- -------------------------------------------------- ----- ------------ ----------

7839          1 |= -> KING                                               根节点       KING

7566          2   |= -> KING -> JONES                               7839 根节点       KING

7788          3     |= -> KING -> JONES -> SCOTT                    7566 根节点       KING

7876          4       |= -> KING -> JONES -> SCOTT -> ADAMS         7788     叶子节点 KING

7902          3     |= -> KING -> JONES -> FORD                     7566 根节点       KING

7369          4       |= -> KING -> JONES -> FORD -> SMITH          7902     叶子节点 KING

7782          2   |= -> KING -> CLARK                               7839 根节点       KING

7934          3     |= -> KING -> CLARK -> MILLER                   7782     叶子节点 KING

8 rows selected

4、order siblings by

在层次查询中,如果最终使用了order by子句进行排序,则会破坏最终的层次结构;而如果想保持层次结构同时在每层内进行排序则需要使用order siblings by子句。

SQL> select empno,

2         level,

3         lpad('|=', level * 2, ' ') || ename as sortname,

4         lpad('|=', level * 2, ' ') || sys_connect_by_path(ename, ' -> ') as empname,

5         mgr,

6         decode(connect_by_isleaf, 0, '根节点', 1, '    叶子节点') as isleaf,

7         connect_by_root ename as rootname

8    from emp

9  connect by prior empno = mgr

10   start with mgr is null

11   order by ename;

EMPNO      LEVEL SORTNAME             EMPNAME                                              MGR ISLEAF       ROOTNAME

----- ---------- -------------------- -------------------------------------------------- ----- ------------ ----------

7876          4       |=ADAMS              |= -> KING -> JONES -> SCOTT -> ADAMS         7788     叶子节点 KING

7499          3     |=ALLEN              |= -> KING -> BLAKE -> ALLEN                    7698     叶子节点 KING

7698          2   |=BLAKE              |= -> KING -> BLAKE                               7839 根节点       KING

7782          2   |=CLARK              |= -> KING -> CLARK                               7839 根节点       KING

7902          3     |=FORD               |= -> KING -> JONES -> FORD                     7566 根节点       KING

7900          3     |=JAMES              |= -> KING -> BLAKE -> JAMES                    7698     叶子节点 KING

7566          2   |=JONES              |= -> KING -> JONES                               7839 根节点       KING

7839          1 |=KING               |= -> KING                                               根节点       KING

7654          3     |=MARTIN             |= -> KING -> BLAKE -> MARTIN                   7698     叶子节点 KING

7934          3     |=MILLER             |= -> KING -> CLARK -> MILLER                   7782     叶子节点 KING

7788          3     |=SCOTT              |= -> KING -> JONES -> SCOTT                    7566 根节点       KING

7369          4       |=SMITH              |= -> KING -> JONES -> FORD -> SMITH          7902     叶子节点 KING

7844          3     |=TURNER             |= -> KING -> BLAKE -> TURNER                   7698     叶子节点 KING

7521          3     |=WARD               |= -> KING -> BLAKE -> WARD                     7698     叶子节点 KING

14 rows selected

SQL> select empno,

2         level,

3         lpad('|=', level * 2, ' ') || ename as sortname,

4         lpad('|=', level * 2, ' ') || sys_connect_by_path(ename, ' -> ') as empname,

5         mgr,

6         decode(connect_by_isleaf, 0, '根节点', 1, '    叶子节点') as isleaf,

7         connect_by_root ename as rootname

8    from emp

9  connect by prior empno = mgr

10   start with mgr is null

11   order siblings by ename;

EMPNO      LEVEL SORTNAME             EMPNAME                                              MGR ISLEAF       ROOTNAME

----- ---------- -------------------- -------------------------------------------------- ----- ------------ ----------

7839          1 |=KING               |= -> KING                                               根节点       KING

7698          2   |=BLAKE              |= -> KING -> BLAKE                               7839 根节点       KING

7499          3     |=ALLEN              |= -> KING -> BLAKE -> ALLEN                    7698     叶子节点 KING

7900          3     |=JAMES              |= -> KING -> BLAKE -> JAMES                    7698     叶子节点 KING

7654          3     |=MARTIN             |= -> KING -> BLAKE -> MARTIN                   7698     叶子节点 KING

7844          3     |=TURNER             |= -> KING -> BLAKE -> TURNER                   7698     叶子节点 KING

7521          3     |=WARD               |= -> KING -> BLAKE -> WARD                     7698     叶子节点 KING

7782          2   |=CLARK              |= -> KING -> CLARK                               7839 根节点       KING

7934          3     |=MILLER             |= -> KING -> CLARK -> MILLER                   7782     叶子节点 KING

7566          2   |=JONES              |= -> KING -> JONES                               7839 根节点       KING

7902          3     |=FORD               |= -> KING -> JONES -> FORD                     7566 根节点       KING

7369          4       |=SMITH              |= -> KING -> JONES -> FORD -> SMITH          7902     叶子节点 KING

7788          3     |=SCOTT              |= -> KING -> JONES -> SCOTT                    7566 根节点       KING

7876          4       |=ADAMS              |= -> KING -> JONES -> SCOTT -> ADAMS         7788     叶子节点 KING

14 rows selected

5、connect_by_iscycle

在进行层次查询时,最重要的是根据指定的数据确定数据间的层次关系,但是有时候会出现死循环的情况。在oracle中提供了connect_by_iscycle伪列用于判断是否出现了死循环,如果出现循环,则返回1,否则返回0.同时要判断是否为循环节点,需要nocycle的支持。

SQL> update emp set mgr = 7698 where empno = 7839;

1 row updated

SQL> commit;

Commit complete

SQL> select empno,

2         level,

3         lpad('|=', level * 2, ' ') || ename as sortname,

4         decode(connect_by_isleaf, 1, '根节点', 0, '    叶子节点') as isleaf,

5         decode(connect_by_iscycle, 1, '【X】存在循环', 0, '【√】没有循环') as iscycle,

6         mgr

7    from emp

8  connect by nocycle prior empno = mgr

9   start with mgr = 7839

10   order siblings by ename;

EMPNO      LEVEL SORTNAME             ISLEAF       ISCYCLE          MGR

----- ---------- -------------------- ------------ -------------- -----

7698          1 |=BLAKE                  叶子节点 【√】没有循环  7839

7499          2   |=ALLEN            根节点 【√】没有循环  7698

7900          2   |=JAMES            根节点 【√】没有循环  7698

7839          2   |=KING                 叶子节点 【X】存在循环   7698

7782          3     |=CLARK              叶子节点 【√】没有循环  7839

7934          4       |=MILLER       根节点 【√】没有循环  7782

7566          3     |=JONES              叶子节点 【√】没有循环  7839

7902          4       |=FORD             叶子节点 【√】没有循环  7566

7369          5         |=SMITH      根节点 【√】没有循环  7902

7788          4       |=SCOTT            叶子节点 【√】没有循环  7566

7876          5         |=ADAMS      根节点 【√】没有循环  7788

7654          2   |=MARTIN           根节点 【√】没有循环  7698

7844          2   |=TURNER           根节点 【√】没有循环  7698

7521          2   |=WARD             根节点 【√】没有循环  7698

7782          1 |=CLARK                  叶子节点 【√】没有循环  7839

7934          2   |=MILLER           根节点 【√】没有循环  7782

7566          1 |=JONES                  叶子节点 【√】没有循环  7839

7902          2   |=FORD                 叶子节点 【√】没有循环  7566

7369          3     |=SMITH          根节点 【√】没有循环  7902

7788          2   |=SCOTT                叶子节点 【√】没有循环  7566

7876          3     |=ADAMS          根节点 【√】没有循环  7788

21 rows selected

SQL> update emp set mgr = null where empno = 7839;

1 row updated

SQL> commit;

Commit complete

SQL之层次查询的更多相关文章

  1. SQL Fundamentals: 子查询 || 行列转换(PIVOT,UNPIVOT,DECODE),设置数据层次(LEVEL...CONNECT BY)

    SQL Fundamentals || Oracle SQL语言 子查询(基础) 1.认识子查询 2.WHERE子句中使用子查询 3.在HAVING子句中使用子查询 4.在FROM子句中使用子查询 5 ...

  2. Oracle层次查询

    Oracle层次查询的语法如下: 下面根据两道“烧脑”的题具体来体现: 1. 根据时间先后顺序,十二星座的英文名称用逗号串起来为'Aries,Taurus,Gemini,Cancer,Leo,Virg ...

  3. oracle层次查询的陷阱

    今天开发组同事找到我,说一个简单的层次查询非常慢,业务就是有一个存设备表连接关系的表,从node1连入,从node2连出,现在要找出node2的连出顺序,sql类似于: SELECT LEVEL ID ...

  4. 【转载】Oracle层次查询和分析函数

    摘要 一组连续的数,去掉中间一些数,如何求出剩下的数的区间(即号段)?知道号段的起止,如何求出该号段内所有的数?知道一个大的号段范围和已经取过的号段,如何求出可用的号段?利用Oracle提供的强大的查 ...

  5. SQL基础-->层次化查询(START BY ... CONNECT BY PRIOR)[转]

    --====================================================== --SQL基础-->层次化查询(START BY ... CONNECT BY ...

  6. SQL Fundamentals: 子查询 || 分析函数(PARTITION BY,ORDER BY, WINDOWING)

    SQL Fundamentals || Oracle SQL语言 子查询(基础) 1.认识子查询 2.WHERE子句中使用子查询 3.在HAVING子句中使用子查询 4.在FROM子句中使用子查询 5 ...

  7. Oracle层次查询和分析函数在号段选取中的应用

    转自:http://www.itpub.net/thread-719692-1-1.html 摘要一组连续的数,去掉中间一些数,如何求出剩下的数的区间(即号段)?知道号段的起止,如何求出该号段内所有的 ...

  8. SQL Fundamentals: 子查询 || WHERE,HAVING,FROM,SELECT子句中使用子查询,WITH子句

    SQL Fundamentals || Oracle SQL语言 子查询(基础) 1.认识子查询 2.WHERE子句中使用子查询 3.在HAVING子句中使用子查询 4.在FROM子句中使用子查询 5 ...

  9. Oracle - 层次查询

    如果表中含有层次数据,可以通过使用层次查询有序地查看层次数据. 语法: condition:指一个或多个表达式和逻辑(布尔)运算符的组合,并返回TRUE.FALSE或UNKNOWNstart with ...

随机推荐

  1. android sdk manager 代理设置

    启动 Android SDK Manager ,打开主界面,依次选择「Tools」.「Options...」,弹出『Android SDK Manager - Settings』窗口: 在『Andro ...

  2. Socket网络编程--聊天程序(3)

    上一小节,已经讲到可以每个人多说话,而且还没有限制,简单的来说,我们已经完成了聊天的功能了,那么接下来我们要实现什么功能呢?一个聊天程序至少应该支持一对多的通讯吧,接下来就实现多个客户端往服务器发送数 ...

  3. maven的配置及一些常用命令

    一般来说,github上大多的java项目都是使用maven,ant等进行构建的.由于之前没有使用过maven,因此这几天对maven进行了简单的学习.古话说:“温故而知新”,一些命令长时间不使用都会 ...

  4. linux每日命令(24):Linux 目录结构

    一. 简介 对于每一个Linux学习者来说,了解Linux文件系统的目录结构,是学好Linux的至关重要的一步.,深入了解linux文件目录结构的标准和每个目录的详细功能,对于我们用好linux系统只 ...

  5. 启动TDS LDAP 服务器遇到的问题总结

    在启动TDS LDAP服务器时遇到一些问题,由于习惯使用Oracle数据库,而对DB2数据库比较陌生,在遇到这些问题时也是摸不到头脑,好在现在解决了,并把所遇到的问题罗列如下: 使用命令启动TDS L ...

  6. segMatch:基于3D点云分割的回环检测

    该论文的地址是:https://arxiv.org/pdf/1609.07720.pdf segmatch是一个提供车辆的回环检测的技术,使用提取和匹配分割的三维激光点云技术.分割的例子可以在下面的图 ...

  7. Java如何找到一个单词的每一次匹配?

    在Java编程中,如何查找字符串中特定单词的最后一个索引? 以下示例演示如何使用Matlass类的matchet.find()方法和Pattern类的Patter.compile()方法查找字符串中指 ...

  8. oracle 11G rac 11.2.0.1 打补丁9413827

    这是升级到以后11.2.0.2.11.2.0.3.11.2.0.4的基础 主要参考两篇文章: Upgrade_11.2.0.1_GI_CRS_to_11.2.0.2_in_Linux.PDF文件 ht ...

  9. python加快数据处理的方法

    1.一切数据库操作最好使用内网连接, 2.使用批量操作接口操作数据库,而不是多线程频繁操作单条数据 3.如果python进程的cpu使用率达到100%了,需要开启多进程.java单个进程cpu使用率在 ...

  10. 中文数据解码报错 UnicodeDecodeError: 'gbk' codec can't decode bytes in position 2-3: illegal multibyte sequence

    UnicodeDecodeError: 'gbk' codec can't decode bytes in position 2-3: illegal multibyte sequence 失败原因: ...