SQL Server 2005中的CTE遞迴查詢得到一棵樹

來源:互聯網
上載者:User

標籤:style   blog   http   io   ar   os   使用   sp   資料   

感覺這個CTE遞迴查詢蠻好用的,先舉個例子:

 

[c-sharp] view plain copy print ?
  1. use City;  
  2. go  
  3. create table Tree  
  4. (  
  5.   ID int identity(1,1) primary key not null,  
  6.   Name varchar(20) not null,  
  7.   Parent varchar(20) null  
  8. )  
  9. go  
  10. insert Tree values(‘大學‘,null)  
  11. insert Tree values(‘學院‘,‘大學‘)  
  12. insert Tree values(‘電腦學院‘,‘學院‘)  
  13. insert Tree values(‘網路工程‘,‘電腦學院‘)  
  14. insert Tree values(‘資訊管理‘,‘電腦學院‘)  
  15. insert Tree values(‘電信學院‘,‘學院‘)  
  16. insert Tree values(‘教務處‘,‘大學‘)  
  17. insert Tree values(‘材料科‘,‘教務處‘)  
  18. insert Tree values(‘招生辦‘,‘大學‘)  
  19. go  
  20. with CTE as  
  21. (  
  22. -->Begin 一個錨點成員  
  23.  select ID, Name,Parent,cast(Name as nvarchar(max)) as TE,0 as Levle from Tree where Parent is null  
  24. -->End   
  25. union all  
  26. -->Begin一個遞迴成員  
  27.  select Tree.ID, Tree.Name,Tree.Parent,cast(replicate(‘ ‘,len(CTE.TE))+‘|_‘+Tree.name as nvarchar(MAX)) as TE,Levle+1 as Levle  
  28.         from Tree inner join CTE  
  29.         on Tree.Parent=CTE.Name  
  30. -->End  
  31. )  
  32. select * from CTE order by ID  
  33. --1.將 CTE 運算式拆分為錨點成員和遞迴成員。  
  34. --2.運行錨點成員,建立第一個調用或基準結果集 (T0)。  
  35. --3.運行遞迴成員,將 Ti 作為輸入(這裡只有一條記錄),將 Ti+1 作為輸出。  
  36. --4.重複步驟 3,直到返回空集。  
  37. --5.返回結果集。這是對 T0 到 Tn 執行 UNION ALL 的結果。  

上面的SQL語句再次插入一條資料:

insert Tree values(‘網路1班‘,‘網路工程‘)

     運行結果如:

圖1 運行結果

     注意點:貌似在遞迴成員處所選擇的欄位都必須Tree表的資料,而不能是CTE結果集中的除了Tree中沒有而CTE中有的欄位在這裡才可以引用,比如欄位TE。

    首先看下,遍曆的第1條記錄的SQL語句:

[c-sharp] view plain copy print ?
  1. select ID, Name,Parent,cast(Name as nvarchar(max)) as TE,0 as Levle from Tree where Parent is null  

   擷取的結果為:

   Name  Parent   TE    Levle

-------------------------------------

     大學    NULL   大學     0

   遞迴第2次所擷取的結果集合的類SQL語句為:

[c-sharp] view plain copy print ?
  1. select Tree.ID, Tree.Name,Tree.Parent,cast(replicate(‘ ‘,len(CTE.TE))+‘|_‘+Tree.name as nvarchar(MAX)) as TE,Levle+1 as Levle  
  2. from Tree inner join  
  3.    (select ID, Name,Parent,cast(Name as nvarchar(max)) as TE,0 as Levle from Tree where Parent is null)  
  4. as CTE  
  5. on Tree.Parent=CTE.Name  

   上面的CTE子查詢的結果就是第一次遞迴查詢的結果集,上面SQL運行結果為:

   同樣的,將第二次遞迴查詢的上面三條記錄作為第三次查詢的‘定位成員’:

  【這裡要注意,上面的三條記錄是從最後一條開始依次作為第三次遞迴的輸入的,即第一條是ID=9的記錄,接下來是7和2,關於第四次遞迴也類似】

   第三次遞迴類SQL語句

[c-sharp] view plain copy print ?
  1. select Tree.ID, Tree.Name,Tree.Parent,cast(replicate(‘ ‘,len(CTE.TE))+‘|_‘+Tree.name as nvarchar(MAX)) as TE,Levle+1 as Levle  
  2. from Tree inner join  
  3. (第二次遞迴查詢的SQL語句)as CTE  
  4. on Tree.Parent=CTE.Name  

   結果如下:

其實每次遞迴的類SQL可為如下所示:

[c-sharp] view plain copy print ?
  1. select Tree.ID, Tree.Name,Tree.Parent,cast(replicate(‘ ‘,len(CTE.TE))+‘|_‘+Tree.name as nvarchar(MAX)) as TE,Levle+1 as Levle  
  2. from Tree inner join  
  3. (上次遞迴查詢的結果集,僅僅是上次那一次的,而不是以前的總和結果集)  
  4. as CTE  
  5. on Tree.Parent=CTE.Name  

 第四次遞迴一次類推,最後所查詢的結果為上面所有遞迴的union。

 續:在上面的SQ語句查詢結果中,ID為10的記錄應該要放在ID為4的後面。

 往資料表中再次添加兩條記錄:

insert Tree values(‘計科‘,‘電腦學院‘)
insert Tree values(‘我‘,‘網路1班‘) 

再次修改上面的SQL語句:

[c-sharp] view plain copy print ?
  1. with CTE as    
  2. (     
  3. -->Begin 一個錨點成員     
  4.  select ID, Name,Parent,cast(Name as nvarchar(max)) as TE,  
  5.         ROW_NUMBER()over(order by getdate()) as OrderID  
  6.         --最關鍵是上面這個欄位,要擷取排序欄位,按字串來排序。  
  7.         --其中視窗函數必須要使用order by,但是不能用整型,那就用時間吧  
  8.         from Tree where Parent is null    
  9. -->End      
  10. union all     
  11. -->Begin一個遞迴成員     
  12.  select Tree.ID, Tree.Name,Tree.Parent,cast(replicate(‘ ‘,len(CTE.TE))+‘|_‘+Tree.name as nvarchar(MAX)) as TE,  
  13.         CTE.OrderID*100+ROW_NUMBER()over(Order by GETDATE()) as OrderID  
  14.         from Tree inner join CTE     
  15.         on Tree.Parent=CTE.Name     
  16. -->End     
  17. )     
  18. select * from CTE  
  19. order by LTRIM(OrderID)--最後將這個整型資料轉換為字串型的進行排序  
  20.   
  21. --有時候整型可以比大小,字串也可以,字串比的大小是一位一位進行字元比較的  
  22. --整型+字串==整型,只有字串+字串==兩個字串的並和  
  23. --遞迴查詢中:第二條記錄可以引用第一條記錄的值  
  24. --動態載入記錄時,同一個等級的記錄識別符:RowNumber()over(order by getdate())  
  25. --延伸:可以動態擷取某個部門下的所以子部門。也可以擷取該部門上級的所以部門  
  26.   
  27. --總結:首先要拼湊出一個整型資料,然後轉換為字串,最後是進行字串的order,而不是整型資料的order,  

最後的結果為:

圖2 運行結果

這樣,無論使用者插入多少條記錄都可以進行按部門,按規律進行查詢。

SQL Server 2005中的CTE遞迴查詢得到一棵樹

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.