sql 樹狀查詢


; with  cte  as
(
select  from  tb  where  id=@id
union  all
select  a.*  from  tb a  join  cte b  on  a.id=b.pid
) 
select  from  cte
http://bbs.csdn.net/topics/380180222

公用表表達式(Common Table Expression)是SQL SERVER 2005版本之后引入的一個特性.CTE可以看作是一個臨時的結果集,可以在接下來的一個SELECT,INSERT,UPDATE,DELETE,MERGE語句中被多次引用。使用公用表達式可以讓語句更加清晰簡練.

     除此之外,根據微軟對CTE好處的描述,可以歸結為四點:

  •      可以定義遞歸公用表表達式(CTE)
  •      當不需要將結果集作為視圖被多個地方引用時,CTE可以使其更加簡潔
  •     GROUP BY語句可以直接作用於子查詢所得的標量列
  •     可以在一個語句中多次引用公用表表達式(CTE)

 

公用表表達式(CTE)的定義


    公用表達式的定義非常簡單,只包含三部分:

  1.   公用表表達式的名字(在WITH之后)
  2.   所涉及的列名(可選)
  3.   一個SELECT語句(緊跟AS之后)

    在MSDN中的原型:

WITH expression_name [ ( column_name [,...n] ) ] 

AS 

( CTE_query_definition ) 

 

   按照是否遞歸,可以將公用表(CTE)表達式分為遞歸公用表表達式和非遞歸公用表表達式.

 

非遞歸公用表表達式(CTE)


   非遞歸公用表表達式(CTE)是查詢結果僅僅一次性返回一個結果集用於外部查詢調用。並不在其定義的語句中調用其自身的CTE

   非遞歸公用表表達式(CTE)的使用方式和視圖以及子查詢一致

   比如一個簡單的非遞歸公用表表達式:

   1

 

   當然,公用表表達式的好處之一是可以在接下來一條語句中多次引用:

 

   2

 

 

   前面我一直強調“在接下來的一條語句中”,意味着只能接下來一條使用:

   3

 

   由於CTE只能在接下來一條語句中使用,因此,當需要接下來的一條語句中引用多個CTE時,可以定義多個,中間用逗號分隔:

   4

 

遞歸公用表表達式(CTE)


    遞歸公用表表達式很像派生表(Derived Tables ),指的是在CTE內的語句中調用其自身的CTE.與派生表不同的是,CTE可以在一次定義多次進行派生遞歸.對於遞歸的概念,是指一個函數或是過程直接或者間接的調用其自身,遞歸的簡單概念圖如下:

   1

    遞歸在C語言中實現的一個典型例子是斐波那契數列:

long fib(int n)   
{   
     if (n==0) return 0;
   if (n==1) return 1;   
     if (n>1) return fib(n-1)+fib(n-2);
} 

  

   上面C語言代碼可以看到,要構成遞歸函數,需要兩部分。第一部分是基礎部分,返回固定值,也就是告訴程序何時開始遞歸。第二部分是循環部分,是函數或過程直接或者間接調用自身進行遞歸.

 

   對於遞歸公用表達式來說,實現原理也是相同的,同樣需要在語句中定義兩部分:

  •    基本語句
  •    遞歸語句

   在SQL這兩部分通過UNION ALL連接結果集進行返回:

   比如:在AdventureWork中,我想知道每個員工所處的層級,0是最高級

   5

  

 

 

 

   這么復雜的查詢通過遞歸CTE變得如此優雅和簡潔.這也是CTE最強大的地方.

   當然,越強大的力量,就需要被約束.如果使用不當的話,遞歸CTE可能會出現無限遞歸。從而大量消耗SQL Server的服務器資源.因此,SQL Server提供了OPTION選項,可以設定最大的遞歸次數:

   還是上面那個語句,限制了遞歸次數:

   6

   所提示的消息:

   7

 

   這個最大遞歸次數往往是根據數據所代表的具體業務相關的,比如這里,假設公司層級最多只有2層.

 

總結 


    CTE是一種十分優雅的存在。CTE所帶來最大的好處是代碼可讀性的提升,這是良好代碼的必須品質之一。使用遞歸CTE可以更加輕松愉快的用優雅簡潔的方式實現復雜的查詢。

 


免責聲明!

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



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