Oracle遞歸查詢(start with…connect by prior)


查詢基本結構:

select … from table_name
       start with 條件1
       connect by 條件2

1、建測試用表

1 create table test_prior(
2 ids number,
3 son varchar2(200),
4 father varchar2(200)
5 );

並插入數據

start with指定樹的根(即父節點)實際上你還可以指定多個根的,比如 father in ('爺爺', '爸爸')
而connect by prior son = father相當於表名在遞歸的過程中,查找到的樹中其它節點接着又作為根結點。然后繼續遞歸(prior在的一側表示該側為子節點)
為了便於理解可以可以connect by prior那一行當作多余的,只記住要查詢的列名放前面,根列名放等號后面就行,這樣只要指定樹的根結點就比較好理解了。

1 select son
2   from test_prior
3  start with father = '爺爺'
4 connect by prior son = father;
5 
6 select distinct son
7   from test_prior
8  start with father in( '爺爺' , '爸爸' )--指定多個根會出現重復的數據
9 connect by prior son = father;

2、START WITH 可以省略,比如

1 select son from test_prior connect by prior son = father;

此時不指定樹的根的話,就默認把test_prior整個表中的數據從頭到尾遍歷一次,每一個數據做一次根,然后遍歷樹中其他節點信息.
在這個例子中,上面的SQL等價如下:

1 select son
2   from test_prior
3  start with father in ('爺爺', '爸爸', '兒子', '孫子A', '孫子B', '孫子C')
4 connect by prior son = father;

那查詢到的結果如下,有很多重復信息的

3、nocycle關鍵字
我們知道標准的樹結構中是不會有環的,但表中的樹形結構不是標准的,有可能導致環的出現,當然在Oracle中的role是禁止出現循環的.比如你grant A to B ,grant B to C 。再來個grant C to A會出錯的
假如有個上面的環,在再使用開始的遞歸查詢語言會出錯.得用nocycle關鍵字指定忽略環。

1 select son
2   from test_prior
3  start with father = '爺爺'
4 connect by nocycle prior son = father;

其他特性:
1、level關鍵字,代表樹形結構中的層級編號;第一層是數字1,第二層數字2,依次遞增。
2、CONNECT_BY_ROOT方法,能夠獲取第一層集結點結果集中的任意字段的值;例CONNECT_BY_ROOT(字段名)。

1 select t.*,level,son,father,connect_by_root(son)
2   from test_prior t
3  start with father = '爺爺'
4 connect by prior son = father

1 select t.*,level,son,father,connect_by_root(father)
2   from test_prior t
3  start with father = '爺爺'
4 connect by prior son = father

3、實現1到10的序列。

使用rownum或level實現1到10的序列

1 select rownum from dual connect by rownum<=10;
2 select level from dual connect by level<=10;

例:查詢當前時間往前的12周的開始時間、結束時間、第多少周

1 select sysdate - (to_number(to_char(sysdate - 1, 'd')) - 1) -
2        (rownum - 1) * 7 as startDate,
3        sysdate + (7 - to_number(to_char(sysdate - 1, 'd'))) -
4        (rownum - 1) * 7 as endDate,
5        to_number(to_char(sysdate, 'iw')) - rownum + 1 as weekIndex
6   from dual
7 connect by level<= 12;--將level改成rownum可以實現同樣的效果

(注:此為學習記錄筆記,僅供參考若有問題請指正,后續補充......)

參考原文:https://blog.csdn.net/wang_yunj/article/details/51040029

參考原文:https://blog.csdn.net/weiwenhp/article/details/8218091

 


免責聲明!

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



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