Oracle中樹形查詢使用方法


樹形查詢一般用於上下級場合,使用的特殊sql語法包括level,prior,start with,connect by等,下面將就實例來說明其用法。

表定義:

create table tb_hierarchy(
     id number(4,0) primary key,
     name nvarchar2(20) not null,
     pid number(4,0))

充值:

insert into tb_hierarchy(id,name) values('1','Gates');
insert into tb_hierarchy(id,pid,name) values('2','1','Alice');
insert into tb_hierarchy(id,pid,name) values('3','2','Bill');
insert into tb_hierarchy(id,pid,name) values('4','2','Cindy');
insert into tb_hierarchy(id,pid,name) values('5','2','Douglas');
insert into tb_hierarchy(id,pid,name) values('6','1','Eliot');
insert into tb_hierarchy(id,pid,name) values('7','6','Mick');
insert into tb_hierarchy(id,pid,name) values('8','6','Flex');
insert into tb_hierarchy(id,pid,name) values('9','7','張三');
insert into tb_hierarchy(id,pid,name) values('10','7','李四');
insert into tb_hierarchy(id,pid,name) values('11','7','王五');

先讓我們查出員工及其上級:

--列出員工和上級
select level,id,name,(prior name) as mngName
from tb_hierarchy
start with pid is NULL
connect by (prior id)=pid

查詢結果:

SQL> select level,id,name,(prior name) as mngName
  2  from tb_hierarchy
  3  start with pid is NULL
  4  connect by (prior id)=pid;

     LEVEL         ID NAME                                     MNGNAME
---------- ---------- ---------------------------------------- ----------------------------------------
         1          1 Gates
         2          2 Alice                                    Gates
         3          3 Bill                                     Alice
         3          4 Cindy                                    Alice
         3          5 Douglas                                  Alice
         2          6 Eliot                                    Gates
         3          7 Mick                                     Eliot
         4          9 張三                                     Mick
         4         10 李四                                     Mick
         4         11 王五                                     Mick
         3          8 Flex                                     Eliot

已選擇11行。

從上面的level一列可以看出,Gates居於公司領導核心,屬於董事長;他下面是alice,處於總經理地位;Alice下面有三個經理,分別是Bill,Cindy,Douglas...

這些結果是怎么查出來的呢?讓我們看看SQL:

select level,id,name,(prior name) as mngName
from tb_hierarchy
start with pid is NULL
connect by (prior id)=pid

解讀:

level:屬於關鍵字,是和rownum一樣的偽列,代表節點在整棵樹中的層級,如Flex處於等級三,他上面有Eliot,Eliot上面有總頭頭Gates。

prior name:prior屬於關鍵字,代表本條記錄的上一條,如本條是(38,Flex);那么prior就是(26,Eliot);知道了prior是哪一條記錄,我們就知道了prior name是Eliot,prior id就是6。

start with:這個語法告訴樹形查詢應該以pid是空的記錄作為樹的起點。

下面我們來查查以Mick為起點會是什么效果:

SQL> select level,id,name,(prior name) as mngName
  2  from tb_hierarchy
  3  start with name='Mick'
  4  connect by (prior id)=pid;

     LEVEL         ID NAME                                     MNGNAME
---------- ---------- ---------------------------------------- ----------------------------------------
         1          7 Mick
         2          9 張三                                     Mick
         2         10 李四                                     Mick
         2         11 王五                                     Mick

結果查詢出了以Mick為組長,張三李四王五為組員的苦逼外包小組。

在國企干活的人一般稱底下做事的為員,管員的人為基層干部,上下都是干部的為中層干部,上面再沒人的則是首長。

下面我們查查誰是員,誰是基層領導干部,誰是中層領導干部,誰是首長:

SQL> select level,id,name,(prior name) as mngName,
  2  decode(level,1,1) as 首長,
  3  decode(level,2,1) as 中層干部,
  4  decode(level,3,1) as 基層干部,
  5  decode(connect_by_isleaf,1,1) as 員工
  6  from tb_hierarchy
  7  start with pid is NULL
  8  connect by (prior id)=pid;

     LEVEL         ID NAME                 MNGNAME                    首長   中層干部   基層干部       員工
---------- ---------- -------------------- -------------------- ---------- ---------- ---------- ----------
         1          1 Gates                                              1
         2          2 Alice                Gates                                    1
         3          3 Bill                 Alice                                               1          1
         3          4 Cindy                Alice                                               1          1
         3          5 Douglas              Alice                                               1          1
         2          6 Eliot                Gates                                    1
         3          7 Mick                 Eliot                                               1
         4          9 張三                 Mick                                                           1
         4         10 李四                 Mick                                                           1
         4         11 王五                 Mick                                                           1
         3          8 Flex                 Eliot                                               1          1

已選擇11行。

上面的語法中多了一個關鍵字connect_by_isleaf,它表示當前節點下面沒有子節點,或是當前記錄下沒有地位更低的記錄(996!最苦逼的一群人)

下面SQL可以把id前面加點層次:

SQL> select lpad(' ',level,' ')||id AS padid,
  2  level,id,name,(prior name) as mngName,
  3  decode(level,1,1) as 首長,
  4  decode(level,2,1) as 中層干部,
  5  decode(level,3,1) as 基層干部,
  6  decode(connect_by_isleaf,1,1) as 員工
  7  from tb_hierarchy
  8  start with pid is NULL
  9  connect by (prior id)=pid;

PADID           LEVEL         ID NAME       MNGNAME                    首長   中層干部   基層干部    員工
---------- ---------- ---------- ---------- -------------------- ---------- ---------- ---------- ----------
 1                  1          1 Gates                                    1
  2                 2          2 Alice      Gates                                    1
   3                3          3 Bill       Alice                                               1       1
   4                3          4 Cindy      Alice                                               1       1
   5                3          5 Douglas    Alice                                               1       1
  6                 2          6 Eliot      Gates                                    1
   7                3          7 Mick       Eliot                                               1
    9               4          9 張三       Mick                                                        1
    10              4         10 李四       Mick                                                        1
    11              4         11 王五       Mick                                                        1
   8                3          8 Flex       Eliot                                               1       1

已選擇11行。

下面把每個人的上級全列出來:

SQL> col path format a30;
SQL> select level,id,name,(prior name) as mngName,
  2  sys_connect_by_path(name,',') as path
  3  from tb_hierarchy
  4  start with pid is NULL
  5  connect by (prior id)=pid;

     LEVEL         ID NAME       MNGNAME              PATH
---------- ---------- ---------- -------------------- ------------------------------
         1          1 Gates                           ,Gates
         2          2 Alice      Gates                ,Gates,Alice
         3          3 Bill       Alice                ,Gates,Alice,Bill
         3          4 Cindy      Alice                ,Gates,Alice,Cindy
         3          5 Douglas    Alice                ,Gates,Alice,Douglas
         2          6 Eliot      Gates                ,Gates,Eliot
         3          7 Mick       Eliot                ,Gates,Eliot,Mick
         4          9 張三       Mick                 ,Gates,Eliot,Mick,張三
         4         10 李四       Mick                 ,Gates,Eliot,Mick,李四
         4         11 王五       Mick                 ,Gates,Eliot,Mick,王五
         3          8 Flex       Eliot                ,Gates,Eliot,Flex

已選擇11行。

--2020年4月18日--

以上用到的全部SQL:

create table tb_hierarchy(
     id number(4,0) primary key,
     name nvarchar2(20) not null,
     pid number(4,0))
     
insert into tb_hierarchy(id,name) values('1','Gates');
insert into tb_hierarchy(id,pid,name) values('2','1','Alice');
insert into tb_hierarchy(id,pid,name) values('3','2','Bill');
insert into tb_hierarchy(id,pid,name) values('4','2','Cindy');
insert into tb_hierarchy(id,pid,name) values('5','2','Douglas');
insert into tb_hierarchy(id,pid,name) values('6','1','Eliot');
insert into tb_hierarchy(id,pid,name) values('7','6','Mick');
insert into tb_hierarchy(id,pid,name) values('8','6','Flex');
insert into tb_hierarchy(id,pid,name) values('9','7','張三');
insert into tb_hierarchy(id,pid,name) values('10','7','李四');
insert into tb_hierarchy(id,pid,name) values('11','7','王五');

--列出員工和上級
select level,id,name,(prior name) as mngName
from tb_hierarchy
start with pid is NULL
connect by (prior id)=pid

--以mick為起點
select level,id,name,(prior name) as mngName
from tb_hierarchy
start with name='Mick'
connect by (prior id)=pid

--列出是員,基層干部,中級干部和首長
select level,id,name,(prior name) as mngName,
decode(level,1,1) as 首長,
decode(level,2,1) as 中層干部,
decode(level,3,1) as 基層干部,
decode(connect_by_isleaf,1,1) as 員工
from tb_hierarchy
start with pid is NULL
connect by (prior id)=pid

--加入層次列
select lpad(' ',level,' ')||id AS padid,
level,id,name,(prior name) as mngName,
decode(level,1,1) as 首長,
decode(level,2,1) as 中層干部,
decode(level,3,1) as 基層干部,
decode(connect_by_isleaf,1,1) as 員工
from tb_hierarchy
start with pid is NULL
connect by (prior id)=pid

--把上級在path里全列出來
select level,id,name,(prior name) as mngName,
sys_connect_by_path(name,',') as path
from tb_hierarchy
start with pid is NULL
connect by (prior id)=pid

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM