利用SQL 2005 CTE處理樹型資料

2021-09-08 21:00:53 字數 3222 閱讀 3966

在現實生活中,樹型資料屢見不鮮:組織機構,產品結構,人事關係等等......記得在以往的乙個專案中,涉及到機構,人員,在對其進行處理,特別是進行統計,聚集操作的時候,我一直沒找到乙個好的方法.臨時表,檢視,程式控制...能用的辦法都用上了,但在處理效率上一直不盡如人意.歸根結底,我的感覺就是在資料庫中,對資料的操作方式(不管是sql語言,sp,view...)不象程式語言那樣靈活,高效率.

cte(common table expression)是sql server 2005眾多新特性之一.他是乙個可以由定義語句引用的臨時命名結果集.他給我的感覺就是檢視,只不過使用起來更加簡單(不用在create view,drop view之類).更重要的,是他的遞迴功能,這也正是cte真正威力所在.下面就給出乙個簡單的例子.

在這個想象情形中,有類似如下的機構圖:

在資料庫中,建立兩個表:department(機構,部門表)和employee(員工表).表結構和測試資料如下:

department表:

employee表:

現假設如下情形:需要統計各部門(公司)人數的資訊(當乙個人屬於a部門,a部門屬於b公司,則在統計a部門和b公司時,都要把該人計算在內.).現在,我們就可以利用cte強大的遞迴功能:

with

employcte (departmentid)

as(

--base case(anchor member).get all employee

select

departmentid

from

employee

union

all--

recursive member

select

depart.parentid

from

department depart

join

employcte emp

ondepart.departmentid

=emp.departmentid

where

depart.parentid

isnot

null

)select

*from

department depart

--join all department

left

join

( select

employcte.departmentid,

count(*

) as

employeesum

from

employcte

left

join

department depart

ondepart.departmentid

=employcte.departmentid

group

byemploycte.departmentid) empsum

ondepart.departmentid

=empsum.departmentid

通過使用cte,統計每乙個機構(部門)的人數資訊現在只用一句sql語句就搞定了,是不是很令人激動呢:)現在,我們來看一看這條語句:首先,統計的思路是從每乙個人開始,得到乙個人所在的機構,然後遞迴的得到該機構的父機構直到頂級機構(類似於這個人所屬機構的乙個路徑).然後將這個人和路徑上每個機構關聯起來.所有,在sql中,先定義乙個cte----employcte,再定義這個cet遞迴的基(在這個例子中,是所有的員工).然後在遞迴部分,用部門表去連線這個cte本身(他們之間的關聯當然就是departmentid了.這樣,就得到了所有員工所屬機構的路徑.然後,在通過以部門為單位,做一次聚集,就得到了所有機構的人數統計資訊.(說得舌頭都卷了,其實直接看sql,很是簡單明瞭:).

順便,假如,統計每個部門的人數時候,不按照遞迴來統計(假如乙個人屬於a部門,a部門屬於b公司,則統計b公司時候不統計此人).利用cte也是相當簡單:

with

departmenthierarchy (departmentid,departmentname,parentid,hierarchylevel)

as(

--base case

select

departmentid,departmentname,parentid,1as

hierarchylevel

from

department

where

parentid

isnull

union

all--

recursive member

select

depart.departmentid,depart.departmentname,depart.parentid,departhier.hierarchylevel +1

ashierarchylevel

from

department depart

inner

join

departmenthierarchy departhier

ondepart.parentid

=departhier.departmentid ),departandemp(departmentid,departmentname,parentid,hierarchylevel,num)

as(

select

*,employeenum=(

select

count(*

) from

employee

where

departmentid

=departmenthierarchy.departmentid)

from

departmenthierarchy)

select

*from

departandemp

在上面這個例子中,用到了兩個cte,在使用多個cte時,只用逗號將各個cte分開即可.

另外,在使用cte的過程中,也感覺到一些不方便的東西.例如:要想使用乙個cte,必須申明了他之後馬上使用,否則,其後任何使用,會報"invalid object"錯誤.有時我使用完某個cte後,想再使用一次,麻煩就出來了,鬱悶.也不知道ms是怎麼想的還是我沒找他其他辦法?還有,在cte的遞迴部分,不能使用諸如sum,count的聚集函式,這著實讓我鬱悶,不知道是處於實現上的原因還是效能上的原因.如果能使用的話,在做統計聚集的時候cte將會更加簡單方便

轉自:

利用SQL 2005 CTE處理樹型資料

在現實生活中,樹型資料屢見不鮮 組織機構,產品結構,人事關係等等.記得在以往的乙個專案中,涉及到機構,人員,在對其進行處理,特別是進行統計,聚集操作的時候,我一直沒找到乙個好的方法.臨時表,檢視,程式控制.能用的辦法都用上了,但在處理效率上一直不盡如人意.歸根結底,我的感覺就是在資料庫中,對資料的操...

sql 2005 迴圈處理資料

對oracle而言用游標很容易就可以實現,也不會太耗費資源 相對來說 而sql用游標確相當的慢,以下用row number實現的乙個迴圈處理 declare date datetime,maxid int id int begin select maxid count from nt fundchi...

SQL2005中利用儲存過程分頁

進行top查詢時 引數需要帶上 declare page int,pagesize int set page 2 select top page from usertb 分頁 select top 2 from usertb where userid not in select top 2 user...