Oracle connet by prior 关键字的简单介绍和用法
??????? 簡單來講,?? connect by piror 這個(gè)關(guān)鍵字是用來保存樹結(jié)構(gòu)的關(guān)系表的.
???
一, 樹結(jié)構(gòu)簡單介紹
? ?? ?? 這里都簡單解釋一下樹結(jié)構(gòu),?? 所謂樹就是里面的成員除了最上級(jí)的成員外,? 有且只有一個(gè)上級(jí)成員,? 而且可以n個(gè)下級(jí)成員(n>=0). 最上級(jí)的成員沒有上級(jí)成員.
??????? 在現(xiàn)實(shí)中, 一間公司的人事結(jié)構(gòu)可以用樹來表示啦, 前提是1個(gè)員工不能有兩個(gè)直屬上司, 不然都不知道聽哪個(gè)啊是不是.
??????? 當(dāng)然, 上面的解釋是不嚴(yán)謹(jǐn)?shù)? 嚴(yán)謹(jǐn)?shù)慕馕鼍鸵プx一讀數(shù)據(jù)結(jié)構(gòu)啦.
二, 雙親表示法保存樹結(jié)構(gòu).
2.1 存儲(chǔ)原理
? ? ? ? ? 例如我要保存1個(gè)簡單的人事結(jié)構(gòu)如下圖:
? ? ? ? ??
? ? ? ? ? ? ? ? ? 1. Nedved
? ? ? ? ? ? ? ? ? ? ? / ? ? ? ? ? \ ??
???????? 2. Jason?????? 3.Hebe
??????????? /????? ? ? ? \
? 4.David??????? 5.Peter
???????????????????????? /???????? \
???????????????? 6. Jacky??? 7.Bill
??????? 怎么把上面的結(jié)構(gòu)保存入數(shù)據(jù)庫的一張表?? 通常的做法是為表里的成員設(shè)置1個(gè)唯一的key (id), 而且設(shè)置1個(gè)parent_id, 存放的是這個(gè)成員的父成員的id.
??????? 這種利用id 和 parent_id 來表示樹結(jié)構(gòu)的方法實(shí)際上就是 "雙親表示法" 詳細(xì)可以參考下面鏈接:
??????? http://blog.csdn.net/nvd11/article/details/8872842
2.2 建表
???????? 了解原理后, 建表就很簡單了, 總之這張表必須包含3個(gè)列,? 分別是 id, name , p_id
2.3 插入數(shù)據(jù)
???????? 插入數(shù)據(jù)也不難,? 只需要知道每個(gè)數(shù)據(jù)列的父級(jí)就ok.?? 但是我們上面提過了, 最上級(jí)的成員(Nedved) 是沒有父級(jí)的, 一般會(huì)將Nedved行的p_id 設(shè)成NULL,? 但是這種情況有時(shí)會(huì)影響檢索(索引失效),? 所以我們盡量避免NULL值出現(xiàn)在表中, 所以最好把Nedved的p_id 設(shè)成0.
????????? 插入數(shù)據(jù)的語句如下:
delete from tree_1;insert into tree_1 values(1, 'Nedved' , 0); insert into tree_1 values(2, 'Jason' , 1); insert into tree_1 values(3, 'Hebe' , 1); insert into tree_1 values(4, 'David' , 2); insert into tree_1 values(5, 'Peter' , 2); insert into tree_1 values(6, 'Jacky' , 5); insert into tree_1 values(7, 'Bill' , 5); commit;好了, 到這步為止我們已經(jīng)把1個(gè)簡單的樹結(jié)構(gòu)保存如一張關(guān)系數(shù)據(jù)表啦.
三, 檢索數(shù)據(jù)
3.1 查找某個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn)
?????? 這個(gè)很簡單了,? 例如我想查找Jason上司是誰? (已知Jason的id是2)
?????? 直接根據(jù)pid查找就ok啦.
select a.* from tree_1 a, tree_1 b where a.id = b.p_id and b.id = 2輸出: ID NAME P_ID ---------- -------------------- ----------1 Nedved 0
3.2 查找某個(gè)節(jié)點(diǎn)的所有子節(jié)點(diǎn).
這里的子節(jié)點(diǎn)是直某個(gè)節(jié)點(diǎn)的下一級(jí)的節(jié)點(diǎn). 例如我想查找Jason的直接下屬. 那么就應(yīng)該找出David 和 Peter,? 而Peter的下屬Jacky和Bill就不屬于Jason的子節(jié)點(diǎn)了.
方法都很簡單,? 查找p_id的值是Jason的id就ok啦.
SQL> select * from tree_1 where p_id = 2 /*Jason's id*/;ID NAME P_ID ---------- -------------------- ----------4 David 25 Peter 2SQL>3.3 查找某個(gè)節(jié)點(diǎn)的所有子孫節(jié)點(diǎn).
這里的子孫就龐大了,? 實(shí)際就是找1個(gè)節(jié)點(diǎn)的所有后代節(jié)點(diǎn),?
例如我想找Jason的所有后代節(jié)點(diǎn):
首先 當(dāng)然包括David 和 Peter啦, 而Peter的后代也是Jason的后代啊, 所以要把Jacky 和 Bill也找出來.
這里看來并不復(fù)雜啊, 是因?yàn)槲疫@個(gè)樹結(jié)構(gòu)太淺了, 實(shí)際上常規(guī)的sql語句寫法是很難實(shí)現(xiàn)的,? 假如Bill也有后代....? 也就是說很難根據(jù)1個(gè)節(jié)點(diǎn)判斷他的最深的后代去哪一層啊.
當(dāng)然利用循環(huán)和臨時(shí)表是能解決問題的, 但是sql語句就相當(dāng)復(fù)雜了.
Oracle中有個(gè)關(guān)鍵字" connect by "? 就是在這種情況下發(fā)揮作用的, 通常和"start with"字句一同使用.
例如這個(gè)小節(jié), 我要找出Jason的所有直接和非直接的下屬.
就可以利用如下語句:
select * from tree_1 start with id = 2 --Jason's id connect by prior id = p_id;輸出:
ID NAME P_ID ---------- -------------------- ----------2 Jason 14 David 25 Peter 26 Jacky 57 Bill 5我們來分析下這條語句:
1)? 首先? connect by prior id = p_id?? 也可寫成 connect by p_id = prior id, 關(guān)鍵是prior的位置是在 id 的前面還是 parent id 的前面.
2) 如果prior 關(guān)鍵字在id前面, 就相當(dāng)對(duì)1個(gè)樹從根節(jié)點(diǎn)往下面遍歷所有節(jié)點(diǎn)了!
3) 例如上面例子,? start with字句就是用來決定跟節(jié)點(diǎn)的位置的,? 實(shí)際上就是遍歷以Jason 為跟節(jié)點(diǎn)的字樹啊. 看輸出結(jié)果, 明顯是1個(gè)先序遍歷行為.? 至于樹的遍歷知識(shí)可以參考我的博文中的數(shù)據(jù)結(jié)構(gòu)部分.
4) 如果只想得出Jason的所有子孫節(jié)點(diǎn), 不需要把Jason本身也select出來, 可以在 start with字句上面加上 where id <>2 子句.
3.4 查找某個(gè)節(jié)點(diǎn)的所有祖輩
例如我想找出Bill的所有直接和間接的上司(上司的上司).
Oracle 中 connect by字句同樣可以方便的實(shí)現(xiàn)這個(gè)功能,
關(guān)鍵就是prior 的位置要在parent id前面
語句如下:
select * from tree_1 start with id = 7 --Bill's id connect by id = prior p_id;留意 prior 關(guān)鍵字的位置啊.
輸出:
ID NAME P_ID ---------- -------------------- ----------7 Bill 55 Peter 22 Jason 11 Nedved 0
總結(jié)
以上是生活随笔為你收集整理的Oracle connet by prior 关键字的简单介绍和用法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c语言位运算 求1个整数的二进制数有多少
- 下一篇: Oracle 的关联子查询(correl