oracle樹形結(jié)構(gòu)層級查詢之start with ....connect by prior、level、order by以及sys_connect_by_path之淺談

淺談oracle樹狀結(jié)構(gòu)層級查詢

原文地址:淺談oracle樹狀結(jié)構(gòu)層級查詢

oracle樹狀結(jié)構(gòu)查詢即層次遞歸查詢,是sql語句經(jīng)常用到的,在實際開發(fā)中組織結(jié)構(gòu)實現(xiàn)及其層次化實現(xiàn)功能也是經(jīng)常遇到的,雖然我是一個java程序開發(fā)者,我一直覺得只要精通數(shù)據(jù)庫那么對于java開發(fā)你就成功了三分之一,本篇中主要介紹start with...connect by prior 、order by 、sys_connect_by_path。

概要:樹狀結(jié)構(gòu)通常由根節(jié)點、父節(jié)點、子節(jié)點和葉節(jié)點組成,簡單來說,一張表中存在兩個字段,dept_id,par_dept_id,那么通過找到每一條記錄的父級id即可形成一個樹狀結(jié)構(gòu),也就是par_dept_id(子)=dept_id(父),通俗的說就是這條記錄的par_dept_id是另外一條記錄也就是父級的dept_id,其樹狀結(jié)構(gòu)層級查詢的基本語法是:

SELECT [LEVEL],*

FEOM table_name

START WITH 條件1

CONNECT BY PRIOR 條件2

WHERE 條件3

ORDER BY 排序字段

說明:LEVEL---偽列,用于表示樹的層次

條件1---根節(jié)點的限定條件,當然也可以放寬權(quán)限,以獲得多個根節(jié)點,也就是獲取多個樹

條件2---連接條件,目的就是給出父子之間的關(guān)系是什么,根據(jù)這個關(guān)系進行遞歸查詢

條件3---過濾條件,對所有返回的記錄進行過濾。

排序字段---對所有返回記錄進行排序

對prior說明:要的時候有兩種寫法:connect by prior dept_id=par_dept_id或connect by dept_id=prior par_dept_id,前一種寫法表示采用自上而下的搜索方式(先找父節(jié)點然后找子節(jié)點),后一種寫法表示采用自下而上的搜索方式(先找葉子節(jié)點然后找父節(jié)點)。

樹狀結(jié)構(gòu)層次化查詢需要對樹結(jié)構(gòu)的每一個節(jié)點進行訪問并且不能重復(fù),其訪問步驟為:

大致意思就是掃描整個樹結(jié)構(gòu)的過程即遍歷樹的過程,其用語言描述就是:

步驟一:從根節(jié)點開始;

步驟二:訪問該節(jié)點;

步驟三:判斷該節(jié)點有無未被訪問的子節(jié)點,若有,則轉(zhuǎn)向它最左側(cè)的未被訪問的子節(jié),并執(zhí)行第二步,否則執(zhí)行第四步;

步驟四:若該節(jié)點為根節(jié)點,則訪問完畢,否則執(zhí)行第五步;

步驟五:返回到該節(jié)點的父節(jié)點,并執(zhí)行第三步驟。

除此之外,sys_connect_by_path函數(shù)是和connect? by 一起使用的,在實戰(zhàn)中具體帶目的具體介紹!

實戰(zhàn):最近做項目的組織結(jié)構(gòu),對于部門的各級層次顯示,由于這部分掌握不牢固,用最笨的like模糊查詢解決了,雖然功能實現(xiàn)了,但是問題很多,如擴展性不好,稍微改下需求就要進行大改,不滿意最后對其進行了優(yōu)化。在開發(fā)中能用數(shù)據(jù)庫解決的就不要用java去解決,這也是我一直保持的想法并堅持著。

對于建表語句及其測試數(shù)據(jù)我放在另外一篇博客中,需要進行測試的可以過去拷貝運行測試驗證下!

博客地址:淺談oracle樹狀結(jié)構(gòu)層級查詢測試數(shù)據(jù)

在這張表中有三個字段:dept_id 部門主鍵id;dept_name? 部門名稱;dept_code 部門編碼;par_dept_id? ?父級部門id(首級部門為 -1);

當前節(jié)點遍歷子節(jié)點(遍歷當前部門下所有子部門包括本身)

5selectt.dept_id, t.dept_name, t.dept_code, t.par_dept_id,level

fromSYS_DEPT t

startwitht.dept_id ='40288ac45a3c1e8b015a3c28b4ae01d6'

connectbypriort.dept_id = t.par_dept_id

orderbylevel, t.dept_code

結(jié)果:

dept_id=40288ac45a3c1e8b015a3c28b4ae01d6 是客運部主鍵,對其下的所有子部門進行遍歷,同時用? order by level,dept_code 進行排序 以便達到實際生活中想要的數(shù)據(jù);共31條數(shù)據(jù),部分數(shù)據(jù)如圖所示:

但是:

有問題啊,如果你想在上面的數(shù)據(jù)中獲取層級在2也就是level=2的所有部門,發(fā)現(xiàn)剛開始的時候介紹的語言不起作用?并且會報ORA-00933:sql命令未正確結(jié)束,why?

這個我暫時也沒有得到研究出理論知識,但是改變下where level='2'的位置發(fā)現(xiàn)才會可以的。錯誤的和正確的sql我們對比一下,以后會用就行,要是路過的大神知道為什么,還請告知下,萬分感謝!

錯誤sql:

6selectt.dept_id, t.dept_name, t.dept_code, t.par_dept_id,level

fromSYS_DEPT t

startwitht.dept_id ='40288ac45a3c1e8b015a3c28b4ae01d6'

connectbypriort.dept_id = t.par_dept_id

wherelevel='2'

orderbylevel, t.dept_code

正確sql:

6selectt.dept_id, t.dept_name, t.dept_code, t.par_dept_id,level

fromSYS_DEPT t

wherelevel='2'

startwitht.dept_id ='40288ac45a3c1e8b015a3c28b4ae01d6'

connectbypriort.dept_id = t.par_dept_id

orderbylevel, t.dept_code

當然了,這個對其他形式的where過濾所有返回記錄沒有影響的,這個只是一個例外!

sys_connect_by_path函數(shù)求父節(jié)點到子節(jié)點路徑

簡單介紹下,在oracle中sys_connect_by_path與connect by 一起使用,也就是先要有或建立一棵樹,否則無用還會報錯。它的主要作用體現(xiàn)在path上即路徑,是可以吧一個父節(jié)點下的所有節(jié)點通過某個字符區(qū)分,然后鏈接在一個列中顯示。

sys_connect_by_path(column,clear),其中column是字符型或能自動轉(zhuǎn)換成字符型的列名,它的主要目的就是將父節(jié)點到當前節(jié)點的“path”按照指定的模式出現(xiàn),char可以是單字符也可以是多字符,但不能使用列值中包含的字符,而且這個參數(shù)必須是常量,且不允許使用綁定變量,clear不要用逗號。

文字容易讓人疲勞,放圖和代碼吧!

5selectsys_connect_by_path(t.dept_name,'-->'),t.dept_id, t.dept_name, t.dept_code, t.par_dept_id,level

fromSYS_DEPT t

startwitht.dept_id ='40288ac45a3c1e8b015a3c28b4ae01d6'

connectbypriort.dept_id = t.par_dept_id

orderbylevel, t.dept_code

結(jié)果:

結(jié)束語

一個坑兩周時間填平,最近終于休息閑了下來,整理整理加深記憶,好記性不如爛筆頭,不要高估自己的記性,許久不用很快就會忘記的,在學(xué)習(xí)的道路上,希望自己也希望各位路過的同行不要放棄學(xué)習(xí),任重而道遠!現(xiàn)在的我很菜,以后我會成為大神!哈哈,意淫一下!

愛人是路,朋友是樹,人生有一條路,一條路上有許多樹,有錢的時候別迷路,缺錢的時候靠靠樹,幸福的時候莫忘路,休息的時候澆澆樹。

開心一樂

驚弓之鳥——說的是去面試的剛畢業(yè)大學(xué)生,一聽到用人單位提到行業(yè)經(jīng)驗就落荒而逃的事情;

上聯(lián):做 I T 風(fēng)風(fēng)雨雨 又一年

下聯(lián):賣電腦 辛辛苦苦 每一天

橫批:從小不學(xué)好,長大賣電腦!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,634評論 19 139
  • 幾分鐘 電影 幾分鐘 熱淚 幾秒鐘 心動
    翔于閱讀 261評論 0 1
  • 你不用像刺猬一樣活著,會刺痛別人,也會刺痛自己。 成為小太陽,暖別人的心,也暖到自己的心
    不愛種胡蘿的兔子閱讀 296評論 0 0
  • 9:38pm 歲月還是太長了 和人生一樣 一個人的時候就占了一生的九成 反正我是這樣 也可以說 無聊的時候太多了 ...
    五月和第三天閱讀 197評論 1 2
  • 香格里拉的傳說太多,廣而聞名的有獨克宗古城、普達措公園、梅里雪山等,但很少人知道香格里拉還有個納帕海 —— 一個被...
    有盞茶閱讀 1,900評論 18 19

友情鏈接更多精彩內(nèi)容