隨筆 - 6  文章 - 129  trackbacks - 0
          <2025年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(14)

          隨筆檔案(6)

          文章分類(467)

          文章檔案(423)

          相冊

          收藏夾(18)

          JAVA

          搜索

          •  

          積分與排名

          • 積分 - 826649
          • 排名 - 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('大學',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語句:

          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語句為:

          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語句

          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可為如下所示:

          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語句:

          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 運行結果

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



          posted on 2014-07-17 14:46 Ke 閱讀(748) 評論(0)  編輯  收藏 所屬分類: sql server
          主站蜘蛛池模板: 淄博市| 宜宾市| 玉溪市| 广宁县| 开江县| 察哈| 陇西县| 桂阳县| 临西县| 改则县| 绥棱县| 南澳县| 河东区| 崇义县| 清苑县| 铁岭县| 新余市| 浪卡子县| 如东县| 阜南县| 枣庄市| 永新县| 吴江市| 鄂尔多斯市| 成武县| 远安县| 普兰店市| 任丘市| 惠来县| 百色市| 丰镇市| 湘西| 钟祥市| 珲春市| 白河县| 阜宁县| 淅川县| 东乡族自治县| 洞口县| 吴忠市| 乐都县|