隨筆 - 6  文章 - 129  trackbacks - 0
          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(14)

          隨筆檔案(6)

          文章分類(467)

          文章檔案(423)

          相冊

          收藏夾(18)

          JAVA

          搜索

          •  

          積分與排名

          • 積分 - 826756
          • 排名 - 49

          最新評論

          閱讀排行榜

          評論排行榜

          原文:http://blog.csdn.net/bin_520_yan/article/details/5998349

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

           

          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('大學(xué)',null)  
          11. insert Tree values('學(xué)院','大學(xué)')  
          12. insert Tree values('計算機學(xué)院','學(xué)院')  
          13. insert Tree values('網(wǎng)絡(luò)工程','計算機學(xué)院')  
          14. insert Tree values('信息管理','計算機學(xué)院')  
          15. insert Tree values('電信學(xué)院','學(xué)院')  
          16. insert Tree values('教務(wù)處','大學(xué)')  
          17. insert Tree values('材料科','教務(wù)處')  
          18. insert Tree values('招生辦','大學(xué)')  
          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.運行定位點成員,創(chuàng)建第一個調(diào)用或基準結(jié)果集 (T0)。  
          35. --3.運行遞歸成員,將 Ti 作為輸入(這里只有一條記錄),將 Ti+1 作為輸出。  
          36. --4.重復(fù)步驟 3,直到返回空集。  
          37. --5.返回結(jié)果集。這是對 T0 到 Tn 執(zhí)行 UNION ALL 的結(jié)果。  

           

          上面的SQL語句再次插入一條數(shù)據(jù):

          insert Tree values('網(wǎng)絡(luò)1班','網(wǎng)絡(luò)工程')

               運行結(jié)果如下圖:

          圖1 運行結(jié)果

               注意點:貌似在遞歸成員處所選擇的字段都必須Tree表的數(shù)據(jù),而不能是CTE結(jié)果集中的除了Tree中沒有而CTE中有的字段在這里才可以引用,比如字段TE。

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

          1. select ID, Name,Parent,cast(Name as nvarchar(max)) as TE,0 as Levle from Tree where Parent is null  

           

             獲取的結(jié)果為:

             Name  Parent   TE    Levle

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

               大學(xué)    NULL   大學(xué)     0

             遞歸第2次所獲取的結(jié)果集合的類SQL語句為:

          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子查詢的結(jié)果就是第一次遞歸查詢的結(jié)果集,上面SQL運行結(jié)果為:

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

            【這里要注意,上面的三條記錄是從最后一條開始依次作為第三次遞歸的輸入的,即第一條是ID=9的記錄,接下來是7和2,關(guān)于第四次遞歸也類似】

             第三次遞歸類SQL語句

          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  

           

             結(jié)果如下:

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

          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. (上次遞歸查詢的結(jié)果集,僅僅是上次那一次的,而不是以前的總和結(jié)果集)  
          4. as CTE  
          5. on Tree.Parent=CTE.Name  

           

           第四次遞歸一次類推,最后所查詢的結(jié)果為上面所有遞歸的union。

           續(xù):在上面的SQ語句查詢結(jié)果中,ID為10的記錄應(yīng)該要放在ID為4的后面。

           往數(shù)據(jù)表中再次添加兩條記錄:

          insert Tree values('計科','計算機學(xué)院')
          insert Tree values('我','網(wǎng)絡(luò)1班') 

          再次修改上面的SQL語句:

          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.         --最關(guān)鍵是上面這個字段,要獲取排序字段,按字符串來排序。  
          7.         --其中窗口函數(shù)必須要使用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)--最后將這個整型數(shù)據(jù)轉(zhuǎn)換為字符串型的進行排序  
          20.   
          21. --有時候整型可以比大小,字符串也可以,字符串比的大小是一位一位進行字符比較的  
          22. --整型+字符串==整型,只有字符串+字符串==兩個字符串的并和  
          23. --遞歸查詢中:第二條記錄可以引用第一條記錄的值  
          24. --動態(tài)加載記錄時,同一個等級的記錄識別符:RowNumber()over(order by getdate())  
          25. --延伸:可以動態(tài)獲取某個部門下的所以子部門。也可以獲取該部門上級的所以部門  
          26.   
          27. --總結(jié):首先要拼湊出一個整型數(shù)據(jù),然后轉(zhuǎn)換為字符串,最后是進行字符串的order,而不是整型數(shù)據(jù)的order,  

           

          最后的結(jié)果為:

          圖2 運行結(jié)果

          這樣,無論用戶插入多少條記錄都可以進行按部門,按規(guī)律進行查詢。



          posted on 2014-07-17 14:46 Ke 閱讀(748) 評論(0)  編輯  收藏 所屬分類: sql server
          主站蜘蛛池模板: 重庆市| 清涧县| 珲春市| 昌邑市| 夏邑县| 绍兴市| 米泉市| 察雅县| 富民县| 高邑县| 漳州市| 阿坝县| 闽清县| 武宁县| 福安市| 长垣县| 赣榆县| 四平市| 苏尼特右旗| 涞水县| 安龙县| 宾阳县| 绥阳县| 大关县| 普定县| 从化市| 仁寿县| 无棣县| 金塔县| 东兴市| 长子县| 九龙城区| 织金县| 铜山县| 黑水县| 安达市| 汶川县| 微博| 泰和县| 剑阁县| 河北省|