SQL 基础8.1——层次化查询(START BY ... CONNECT BY PRIOR)

简介:  层次化查询,即树型结构查询,是SQL中经常用到的功能之一,通常由根节点,父节点,子节点,叶节点组成,其语法如下:        SELECT [LEVEL] ,column,expression,.

 层次化查询,即树型结构查询,是SQL中经常用到的功能之一,通常由根节点,父节点,子节点,叶节点组成,其语法如下:

       SELECT [LEVEL] ,column,expression,...

       FROM table_name

       [WHERE where_clause]

       [[START WITH start_condition] [CONNECT BY PRIOR prior_condition]];

      

       LEVEL:为伪列,用于表示树的层次

       start_condition:层次化查询的起始条件

       prior_condition:定义父节点和子节点之间的关系

   

    --使用start with ...connect by prior 从根节点开始遍历

    SQL> select empno,mgr,ename,job from emp

      2  start with empno = 7839

      3  connect by prior empno = mgr;

 

        EMPNO        MGR ENAME      JOB

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

         7839            KING       PRESIDENT

         7566       7839 JONES      MANAGER

         7788       7566 SCOTT      ANALYST

         7876       7788 ADAMS      CLERK

         7902       7566 FORD       ANALYST

         7369       7902 SMITH      CLERK

         7698       7839 BLAKE      MANAGER

         7499       7698 ALLEN      SALESMAN

         7521       7698 WARD       SALESMAN

         7654       7698 MARTIN     SALESMAN

         7844       7698 TURNER     SALESMAN

 

        EMPNO        MGR ENAME      JOB

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

         7900       7698 JAMES      CLERK

         7782       7839 CLARK      MANAGER

         7934       7782 MILLER     CLERK

 

    14 rows selected.

   

    树型结构遍历过程(通过上面的查询来描述)

       1).从根节点开始(即where_clause中的条件,如果为非根节点则分根节点作为根节点开始遍历,如上例empno = 7839)

       2).遍历根节点(得到empno = 7839记录的相关信息)

       3).判断该节点是否存在有子节点,如果有,则访问最左侧未被访问的子节点,转到1否则下一步

           如上例中prior_condition为empno = mgr(下一条查询记录返回的mgr值等于前一条记录的empno),即子节点的mgr等于父节点的empno,在此时下一条的mgr为7839的记录

       4).当节点为叶节点,则访问完毕,进入下一步,否则,转到3

       5).返回到该节点的父节点,转到3)

      

    --伪列level的使用

    --注意connect by prior empno = mgr 的理解

    --prior表示前一条记录,即下一条返回记录的mgr应当等于前一条记录的empno

 

    SQL> select level,empno,mgr,ename,job from emp

      2  start with ename = 'KING'

      3  connect by prior empno = mgr

      4  order by level;

 

        LEVEL      EMPNO        MGR ENAME      JOB

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

            1       7839            KING       PRESIDENT

            2       7566       7839 JONES      MANAGER

            2       7698       7839 BLAKE      MANAGER

            2       7782       7839 CLARK      MANAGER

            3       7902       7566 FORD       ANALYST

            3       7521       7698 WARD       SALESMAN

            3       7900       7698 JAMES      CLERK

            3       7934       7782 MILLER     CLERK

            3       7499       7698 ALLEN      SALESMAN

            3       7788       7566 SCOTT      ANALYST

            3       7654       7698 MARTIN     SALESMAN

 

        LEVEL      EMPNO        MGR ENAME      JOB

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

            3       7844       7698 TURNER     SALESMAN

            4       7876       7788 ADAMS      CLERK

            4       7369       7902 SMITH      CLERK

   

    --获得层次数

    SQL> select count(distinct level) "Level" from emp

      2  start with ename = 'KING'

      3  connect by prior empno = mgr;

 

        Level

    ----------

            4 

            

    --格式化层次查询结果(使用左填充* level - 1个空格)

    SQL> col Ename for a30

    SQL> select level,

      2    lpad(' ',* level - 1) || ename as "Ename",

      3    job

      4  from emp

      5  start with ename = 'KING'

      6  connect by prior empno = mgr;

 

        LEVEL Ename                          JOB

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

            1  KING                          PRESIDENT

            2    JONES                       MANAGER

            3      SCOTT                     ANALYST

            4        ADAMS                   CLERK

            3      FORD                      ANALYST

            4        SMITH                   CLERK

            2    BLAKE                       MANAGER

            3      ALLEN                     SALESMAN

            3      WARD                      SALESMAN

            3      MARTIN                    SALESMAN

            3      TURNER                    SALESMAN

 

        LEVEL Ename                          JOB

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

            3      JAMES                     CLERK

            2    CLARK                       MANAGER

            3      MILLER                    CLERK

 

    14 rows selected.

   

    --从非根节点开始遍历(只需修改start with 中的条件即可)

    SQL> select level,

      2    lpad(' ',* level - 1) || ename as "Ename",

      3    job

      4  from emp

      5  start with ename = 'SCOTT'

      6  connect by prior empno = mgr;

 

        LEVEL Ename                          JOB

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

            1  SCOTT                         ANALYST

            2    ADAMS                       CLERK

 

    --从下向上遍历(交换connect by prior中的条件即可,使用mgr = empno)

    --注意connect by prior mgr = empno 的理解
    --prior表示前一条记录,即下一条返回记录的empno应当等于前一条记录的mgr

 

    SQL> select level,

      2    lpad(' ',* level - 1) || ename as "Ename",

      3    job

      4  from emp

      5  start with ename = 'SCOTT'

      6  connect by prior mgr = empno;

 

        LEVEL Ename                          JOB

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

            1  SCOTT                         ANALYST

            2    JONES                       MANAGER

            3      KING                      PRESIDENT

            

    --从下向上遍历(也可以将prior置于等号右边,得到相同的结果)

    SQL> select level,

      2    lpad(' ',* level - 1) || ename as "Ename",

      3    job

      4  from emp

      5  start with ename = 'SCOTT'

      6  connect by empno = prior mgr;

 

        LEVEL Ename                          JOB

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

            1  SCOTT                         ANALYST

            2    JONES                       MANAGER

            3      KING                      PRESIDENT

            

    --从层次查询中删除节点和分支

    SQL> select level,

      2    lpad(' ',* level - 1) || ename as "Ename"

      3    ,job

      4  from emp

      5  where ename != 'SCOTT'    --通过where子句来过滤SCOTT用户,但SCOTT的下属ADAMS并没有过滤掉

      6  start with empno = 7839   

      7  connect by prior empno = mgr;

 

        LEVEL Ename                JOB

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

            1  KING                PRESIDENT

            2    JONES             MANAGER

            4        ADAMS         CLERK

            3      FORD            ANALYST

            4        SMITH         CLERK

            2    BLAKE             MANAGER

            3      ALLEN           SALESMAN

            3      WARD            SALESMAN

            3      MARTIN          SALESMAN

            3      TURNER          SALESMAN

            3      JAMES           CLERK

 

        LEVEL Ename                JOB

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

            2    CLARK             MANAGER

            3      MILLER          CLERK

 

    13 rows selected.

    

    --通过将过滤条件由where 子句的内容移动到connect by prior 子句中过滤掉SCOTT及其下属

    SQL> select level,

      2    lpad(' ',* level - 1) || ename as "Ename"

      3    ,job

      4  from emp

      5  start with empno = 7839

      6  connect by prior empno = mgr and ename != 'SCOTT';

 

        LEVEL Ename                JOB

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

            1  KING                PRESIDENT

            2    JONES             MANAGER

            3      FORD            ANALYST

            4        SMITH         CLERK

            2    BLAKE             MANAGER

            3      ALLEN           SALESMAN

            3      WARD            SALESMAN

            3      MARTIN          SALESMAN

            3      TURNER          SALESMAN

            3      JAMES           CLERK

            2    CLARK             MANAGER

 

        LEVEL Ename                JOB

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

            3      MILLER          CLERK

 

    12 rows selected.

   

    --在层次化查询中增加过滤条件或使用子查询

    SQL> select level,

      2    lpad(' ',* level - 1) || ename as "Ename"

      3    ,job

      4  from emp

      5  where sal > 2500

      6  start with empno = 7839

      7  connect by prior empno = mgr                     

      8  ;

 

        LEVEL Ename                JOB

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

            1  KING                PRESIDENT

            2    JONES             MANAGER

            3      SCOTT           ANALYST

            3      FORD            ANALYST

            2    BLAKE             MANAGER

            

    SQL> select level,

      2    lpad(' ',* level - 1) || ename as "Ename"

      3    ,job

      4  from emp

      5  where sal > (select avg(sal) from emp)

      6  start with empno = 7839

      7  connect by prior empno = mgr ;

 

        LEVEL Ename                JOB

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

            1  KING                PRESIDENT

            2    JONES             MANAGER

            3      SCOTT           ANALYST

            3      FORD            ANALYST

            2    BLAKE             MANAGER

            2    CLARK             MANAGER

 

    6 rows selected.


目录
打赏
0
0
0
0
53
分享
相关文章
SQL查询太慢?实战讲解YashanDB SQL调优思路
本文是Meetup第十期“调优实战专场”的第二篇技术文章,上一篇《高效查询秘诀,解码YashanDB优化器分组查询优化手段》中,我们揭秘了YashanDB分组查询优化秘诀,本文将通过一个案例,助你快速上手YashanDB慢日志功能,精准定位“慢SQL”后进行优化。
【YashanDB知识库】字段加上索引后,SQL查询不到结果
【YashanDB知识库】字段加上索引后,SQL查询不到结果
OmniSQL:开源文本到SQL神器!自然语言秒转查询到复杂多表连接等SQL需求
OmniSQL是开源的文本到SQL转换模型,通过创新的数据合成框架生成250万条高质量样本,支持7B/14B/32B三种模型版本,能处理从简单查询到复杂多表连接等各种SQL需求。
155 16
OmniSQL:开源文本到SQL神器!自然语言秒转查询到复杂多表连接等SQL需求
玩转大数据:从零开始掌握SQL查询基础
玩转大数据:从零开始掌握SQL查询基础
131 35
如何优化SQL查询以提高数据库性能?
这篇文章以生动的比喻介绍了优化SQL查询的重要性及方法。它首先将未优化的SQL查询比作在自助餐厅贪多嚼不烂的行为,强调了只获取必要数据的必要性。接着,文章详细讲解了四种优化策略:**精简选择**(避免使用`SELECT *`)、**专业筛选**(利用`WHERE`缩小范围)、**高效联接**(索引和限制数据量)以及**使用索引**(加速搜索)。此外,还探讨了如何避免N+1查询问题、使用分页限制结果、理解执行计划以及定期维护数据库健康。通过这些技巧,可以显著提升数据库性能,让查询更高效流畅。
云原生数据仓库AnalyticDB PostgreSQL同一个SQL可以实现向量索引、全文索引GIN、普通索引BTREE混合查询,简化业务实现逻辑、提升查询性能
本文档介绍了如何在AnalyticDB for PostgreSQL中创建表、向量索引及混合检索的实现步骤。主要内容包括:创建`articles`表并设置向量存储格式,创建ANN向量索引,为表增加`username`和`time`列,建立BTREE索引和GIN全文检索索引,并展示了查询结果。参考文档提供了详细的SQL语句和配置说明。
77 1
SQL为什么不建议执行多表关联查询
本文探讨了SQL中不建议执行多表关联查询的原因,特别是MySQL与PG在多表关联上的区别。MySQL仅支持嵌套循环连接,而不支持排序-合并连接和散列连接,因此在多表(超过3张)关联查询时效率较低。文章还分析了多表关联查询与多次单表查询的效率对比,指出将关联操作放在Service层处理的优势,包括减少数据库计算资源消耗、提高缓存效率、降低锁竞争以及更易于分布式扩展等。最后,通过实例展示了如何分解关联查询以优化性能。
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
5-10Can't connect to MySQL server on 'sh-cynosl-grp-fcs50xoa.sql.tencentcdb.com' (110)")
|
9月前
|
SQL Server的并行实施如何优化?
【7月更文挑战第23天】SQL Server的并行实施如何优化?
253 13
|
9月前
|
SQL
解锁 SQL Server 2022的时间序列数据功能
【7月更文挑战第14天】要解锁SQL Server 2022的时间序列数据功能,可使用`generate_series`函数生成整数序列,例如:`SELECT value FROM generate_series(1, 10)。此外,`date_bucket`函数能按指定间隔(如周)对日期时间值分组,这些工具结合窗口函数和其他时间日期函数,能高效处理和分析时间序列数据。更多信息请参考官方文档和技术资料。
159 9

热门文章

最新文章