58 Oracle数据库SQL开发之 高级查询——层次化查询

时间:2021-05-24 00:46:57

58.Oracle数据库SQL开发之 高级查询——层次化查询

        欢迎转载,转载请标明出处:http://blog.csdn.net/notbaron/article/details/49847021

 先执行如下:

store@PDB1> select * from more_employees;

 

EMPLOYEE_ID MANAGER_ID FIRST_NAMELAST_NAME  TITLE                SALARY

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

           1         James           Smith     CEO                         800000

           2       1 Ron        Johnson   Sales Manager              600000

           3       2 Fred       Hobbs     Sales Person        200000

           4       1 Susan    Jones     Support Manager         500000

           5       2 Rob        Green     Sales Person         40000

           6       4 Jane      Brown     Support Person             45000

           7       4 John      Grey          Support Manager         30000

           8       7 Jean      Blue           Support Person             29000

           9       6 Henry    Heyson    Support Person             30000

          10       1 Kevin     Black     Ops Manager        100000

          11      10 Keith     Long          Ops Person          50000

          12      10 Frank     Howard    Ops Person        45000

          13      10 Doreen          Penn          Ops Person          47000

 

13 rows selected.

员工关系如下图1

58 Oracle数据库SQL开发之 高级查询——层次化查询

1.  使用CONNECT BY和START WITH子句

SELECT语句的CONNECT BY和START WITH子句的语法如下所示:

SELECT [LEVEL],column,expression,…

         FROM table

         [WHERE where_clause]

         [[START WITH start_condition] [CONNECTBY PRIOR prior_condition]];

其中,LEVEL是一个 伪列

Start_condition定义了层次化查询的起点。

Prior_condition定义了父行和子行之间的关系。编写层次化查询时必须定义CONNECT BY PRIOR子句。

例如执行:

store@PDB1>select employee_id,manager_id,first_name,last_name from more_employees startwith employee_id = 1 connect by prior employee_id=manager_id;

 

EMPLOYEE_IDMANAGER_ID FIRST_NAME LAST_NAME

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

          1         James           Smith

          2       1 Ron        Johnson

          3       2 Fred       Hobbs

          5       2 Rob        Green

          4       1 Susan    Jones

          6       4 Jane      Brown

          9       6 Henry    Heyson

          7       4 John      Grey

          8       7 Jean      Blue

          10      1 Kevin     Black

          11      10 Keith     Long

          12      10 Frank     Howard

          13      10 Doreen          Penn

 

13 rowsselected.

2.  使用伪列LEVEL

使用伪列LEVEL显示节点在树中的层次:

store@PDB1> selectlevel,employee_id,manager_id,first_name,last_name from more_employees startwith employee_id=1 connect by prior employee_id=manager_id order by level;

 

    LEVEL EMPLOYEE_ID MANAGER_ID FIRST_NAME LAST_NAME

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

          1          1                James     Smith

          2         10              1Kevin      Black

          2          2              1Ron             Johnson

          2          4              1Susan      Jones

          3         13            10 Doreen     Penn

          3          7              4John            Grey

          3         11            10 Keith      Long

          3          5              2Rob             Green

          3          3              2Fred            Hobbs

          3         12            10 Frank      Howard

          3         6              4Jane            Brown

          4          8              7Jean            Blue

          4          9              6Henry      Heyson

 

13 rows selected.

使用COUNT函数和LEVEL来获得树中的层次数

store@PDB1> select count(distinct level) frommore_employees start with employee_id = 1 connect by prioremployee_id=manager_id;

 

COUNT(DISTINCTLEVEL)

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

                      4

3.  格式化层次化查询的结果

可以用LEVEL和LPAD函数对层次化查询结果进行格式化处理,方法是在数据的左边填充字符。

store@PDB1> set pagesize 999

store@PDB1> column employee format a25

store@PDB1> select level,

    lpad('',2*level-1)||first_name||' '||last_name as employee from more_employees

    start withemployee_id=1 connect by prior employee_id = manager_id;

    LEVEL EMPLOYEE

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

          1  JamesSmith

          2    RonJohnson

          3     FredHobbs

          3     RobGreen

          2   Susan Jones

          3     JaneBrown

          4       Henry Heyson

          3     JohnGrey

          4       Jean Blue

          2   Kevin Black

          3     KeithLong

          3     FrankHoward

          3     DoreenPenn

13 rows selected.

4.  从非根节点开始遍历

执行如下:

select level,

    lpad('',2*level-1)||first_name||' '||last_name as employee from more_employees

        startwith last_name=

    'Jones'connect by prior employee_id=manager_id;

    LEVEL EMPLOYEE

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

          1  SusanJones

          2   Jane Brown

          3     HenryHeyson

          2   John Grey

          3     JeanBlue

5.  在START WITH子句中使用子查询

在START WITH子句中可以使用子查询。

store@PDB1> select level,

        lpad('',2*level-1)||first_name||' '||last_name as employee from more_employees

    start withemployee_id=(

    selectemployee_id from more_employees

    wherefirst_name='Kevin'

    andlast_name='Black')

        connectby prior employee_id=manager_id;

    LEVEL EMPLOYEE

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

          1  KevinBlack

          2   Keith Long

          2   Frank Howard

          2   Doreen Penn

6.  从下向上遍历树

不一定非要按照从父节点到子节点的顺序从上至下遍历树。

也可以从给某个子节点开始,自下而上遍历。实现的方法是交换父节点与子节点在CONNECT BY PRIOR子句中的顺序。

执行如下:

select level,

        lpad('',2*level-1)||first_name||' '||last_name as employee from more_employees

    start withlast_name=

'Blue'connect by prior manager_id=employee_id;

    LEVEL EMPLOYEE

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

          1  JeanBlue

          2   John Grey

          3        Susan Jones

          4         JamesSmith

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

select level,

        lpad('',2*level-1)||first_name||' '||last_name as employee from more_employees

        wherelast_name !=

    'Johnson'start with employee_id=1 connect by prior employee_id=manager_id;

 

    LEVEL EMPLOYEE

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

          1  JamesSmith

          3     FredHobbs

          3     RobGreen

          2   Susan Jones

          3     JaneBrown

          4       Henry Heyson

          3     JohnGrey

          4       Jean Blue

          2   Kevin Black

          3     KeithLong

          3     FrankHoward

          3     DoreenPenn

12 rows selected.

为了将整个分支都从查询结果中除去,可以再CONNECT BY PRIOR子句中使用AND子句。

select level,lpad(' ',2*level-1)||first_name||''||last_name as employee from more_employees

   start withemployee_id=1 connect by prior employee_id = manager_id

        andlast_name != 'Johnson';

 

    LEVEL EMPLOYEE

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

          1  JamesSmith

          2   Susan Jones

          3     JaneBrown

          4       Henry Heyson

          3     JohnGrey

          4       Jean Blue

          2   Kevin Black

          3     KeithLong

          3     FrankHoward

          3     DoreenPenn

 

10 rows selected.

8.  在层次化查询中加入其它条件

使用WHERE子句可以再层次化查询中加入其它条件。

执行如下:

store@PDB1> select level,lpad('',2*level-1)||first_name||' '||last_name as employee,salary from more_employeeswhere salary <= 50000 start with employee_id = 1 connect by  prior employee_id = manager_id;

 

    LEVEL EMPLOYEE                     SALARY

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

          3     RobGreen                   40000

          3     JaneBrown                 45000

          4       Henry Heyson                  30000

          3     JohnGrey                     30000

          4       Jean Blue                 29000

          3     KeithLong                    50000

          3     FrankHoward             45000

          3     DoreenPenn               47000

 

8 rows selected.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net