oracle 逆向遞迴查詢 oracle遞迴查詢

2021-10-12 14:17:19 字數 4266 閱讀 6984

oracle的遞迴查詢

最近在看公司的oa系統,oa系統中基本都會有節點樹,其中對於樹上的資料展示,就是用了資料庫的遞迴查詢,在這裡總結下遞迴查詢。

現在存在如下的一棵樹:

不會畫樹,將就一下,該樹對應下面建立的表資料。

建立如下表:

create table dg

id number not null, --主鍵

parent_id number,-- 父節點

childer_id number-- 當前節點,當時名字沒區號,也表示當前的值,即樹中的值

建立如下資料:(除去最後一條資料,其他的資料與樹中的資料嚴格一致)

insert into dg (id , childer_id)values (goods_seq.nextval , 6);

insert into dg (id , parent_id , childer_id) values(goods_seq.nextval,6,10);

insert into dg (id , parent_id , childer_id) values(goods_seq.nextval,10,9);

insert into dg (id , parent_id , childer_id) values(goods_seq.nextval,9,1);

insert into dg (id , parent_id , childer_id) values(goods_seq.nextval,9,2);

insert into dg (id , parent_id , childer_id) values(goods_seq.nextval,6,8);

insert into dg (id , parent_id , childer_id) values(goods_seq.nextval,8,3);

insert into dg (id , parent_id , childer_id) values(goods_seq.nextval,8,4);

insert into dg (id , parent_id , childer_id) values(goods_seq.nextval,10,7);

insert into dg (id , parent_id , childer_id) values(goods_seq.nextval,11,7);

查詢表中的資料如下

select * from dg

idparent_idchilder_id

191.006.00

292.006.0010.00

393.0010.009.00

494.009.001.00

595.009.002.00

696.006.008.00

797.008.003.00

898.008.004.00

999.0010.007.00

10100.0011.007.00

查詢出來的是全部的資料,但是最後一條資料是不在樹這張圖上的,因不存在childer_id為11的記錄

使用遞迴查詢,查詢出樹上的全部資料,不在樹上的記錄不顯示,即某條記錄的parent_id必須是另一條記錄的childer_id,符合該條件的記錄都顯示出來。遞迴存在乙個入口和乙個出口,入口使用start with傳入引數,出口就是某條記錄不滿足這樣的條件了

select * from dg start with childer_id = 6 connect by parent_id = prior childer_id;

idparent_idchilder_id

與上面比較,不在樹中的記錄已經沒有被顯示出來了。

根據記錄的顯示,我們可以看出來記錄是按照深度遍歷的順序排序的,而不是按廣度遍歷的順序排序的

但是在深度遍歷的時候,對於兄弟節點,先遍歷哪個,其實是隨機的,或者說是按照先插入的資料排在前面,後插入的資料排在後面。

但是如果我們需要按照我們的規則對兄弟節點的順序進行排序,這樣的排序明顯不會符合我們。

這裡我們假設根據childer_id的大小排序,使用如下sql:

使用order by排序

select * from dg start with childer_id = 6 connect by parent_id = prior childer_id order by childer_id;

idparent_idchilder_id

雖然按照parent_id來進行排序了,但是整個結果都是按照parent_id來排序了,不再滿足深度遍歷的順序,也就是不分層次了,這樣的結果明顯不是我們想要的。其實除去不在樹中的那條記錄外,這樣的排序時跟下面的排序一致的

select * from dg order by parent_id;

仍然按照深度遍歷的順序排序,但是兄弟節點的排序,使用order sibings by

select * from dg start with childer_id = 6 connect by parent_id = prior childer_id order siblings by childer_id;

idparent_idchilder_id

觀察整個表的記錄,滿足了深度遍歷的排序,觀察3,4 和6,7這兩組記錄發現兄弟節點的排序已經被我們控制了,用的就是order siblings by

5.獲取每條記錄的根節點,使用conect_by_root(field)函式

select dg.*, connect_by_root(childer_id) as childer_root , connect_by_root(parent_id) as parent_root , connect_by_root(id) as id_root from dg start with childer_id = 6 connect by parent_id = prior childer_id

idparent_idchilder_idchilder_rootparent_rootid_root

9166 91

96686 91

97836 91

98846 91

926106 91

991076 91

931096 91

94916 91

95926 91

--其中parent_root這一列是沒有資料的,因為根節點對應的記錄是沒有parent_id值的

這樣就獲取了每條記錄的根節點。因為查詢出來的記錄都是在一棵樹上的,所以肯定所有記錄的根節點資訊都是相同的,通常,我們都是查詢某一條記錄的根節點,只要加個條件就可以了,如下:

select dg.*, connect_by_root(childer_id) as childer_root , connect_by_root(parent_id) as parent_root , connect_by_root(id) as id_root from dg where childer_id = 4 start with childer_id = 6 connect by parent_id = prior childer_id

idparent_idchilder_idchilder_rootparent_rootid_root

98846空91

6.獲取記錄的在樹上的層次(用數字表示,第一層是1,level)和是否是葉子節點(0表示不是,1表示是,connect_by_isleaf)

select id , parent_id , childer_id , level , connect_by_isleaf from dg start with childer_id = 6 connect by parent_id = prior childer_id;

idparent_idchilder_idlevelconnect_by_isleaf

觀察倒數兩列的值,再與上面的樹進行比較

7.顯示節點的遍歷路徑sys_connect_by_path(field,string)

select id , parent_id , childer_id , substring(sys_connect_by_path(childer_id, '->'),3) as path from dg start with childer_id = 6 connect by parent_id = prior childer_id;

idparent_idchilder_idpath

296686->8

397836->8->3

498846->8->4

5926106->10

6991076->10->7

7931096->10->9

894916->10->9->1

995926->10->9->2

oracle 逆向遞迴查詢 Oracle遞迴查詢

start with.connect by子句遞迴查詢一般用於乙個表維護樹形結構的應用。建立示例表 create table tbl test id number,name varchar2 100 byte pid number default 0 插入測試資料 insert into tbl t...

oracle 遞迴查詢 Oracle遞迴查詢

1.1 建立表與插入資料 create table district id number 10 not null,parent id number 10 name varchar2 255 byte not null alter table district add constraint distr...

Oracle遞迴查詢

有的情況下,我們需要用遞迴的方法整理資料,這才程式中很容易做到,但是在資料庫中,用sql語句怎麼實現?下面我以最典型的樹形結構來說明下如何在oracle使用遞迴查詢。為了說明方便,建立一張資料庫表,用於儲存乙個簡單的樹形結構 sql create tabletest tree id number,p...