SQL Server2005雜談(5):將聚合記錄集逆時針和順時針旋轉90度(行列互換)

在輸出統計結果時可能需要將列變成行,而將聚合結果(如count、sum)作爲記錄的第一行,先看如下的SQL語句:
declare @t table(name varchar(20))
insert @t
select 'abc' union all
select 'xxx' union all
select 'xxx' union all
select 'ttt'

select * from @t
    在執行上面的SQL語句後,會輸出如圖1所示的記錄集。
上圖顯示的是一個普通的記錄集,如果要統計name字段的每個值的重複數,需要進行分組,如下面的SQL如示:
select count(name) as c ,name  from @t group by name 

    執行上面的SQL語句後的查詢結果如圖2所示。
如果我們有一個需求,需要如圖3所示的聚合結果。
從圖3可以看出,查詢結果正好是圖2的結果逆時針旋轉90度,也就是說,name列的值變成了列名,而c列的值變成了第一行的記錄。圖2所示的c和name字段消失了。
    當然,要達到這個結果並不困難,看如下的SQL語句:
select (select count(name) from @t where name='abc'as abc, 
       (
select count(name) from @t where name='ttt'as xxx,
       (
select count(name) from @t where name='xxx'as ttt

    上面的SQL語句會出輸出如圖3的查詢結果。但這裏有個問題,上面的SQL語句是枚舉了name列所有可能的值,在本例中只有三個值('abc','ttt','xxx'),這非常好枚舉,但如果有很多值,SQL語句會變得非常長,非常不利於編寫。當然,可以通過編程的方式自動生成,但最終結果仍然會生成很長的SQL語句。
   
爲了解決這個問題,在SQL Server2005中提供了一個pivot函數,該函數可以很容易地輸出如圖3所示的記錄集,如下面的SQL語句所示:
select * from @t pivot(count(name) for name in([abc] ,[ttt],[xxx]))

   
在執行上面的SQL語句同樣可以獲得圖3所示的查詢結果。實際上,pivot函數也起到了分組的作用。在使用pivot函數時應注意如下幾點:
1. pivot函數需要指定聚合函數,如count、sum等,for關鍵字和聚合函數都要使用需要聚合的字段名,在本例中是name。
2. in關鍵字負責指定每組需要聚合的值,用[...]將這些值括起來。實際上,這些值也相當於我們第一種聚合方法中的where條件,例如,where name='abc'、where name='ttt',當然,這些值也是輸出記錄集的列名。
3. 在最後要爲pivot函數起一個別名。

    雖然當要聚合的值很多時(或不確定),也需要動態生成SQL語句,但使用pivot函數的SQL語句卻短很多。
    如果我們還有一個需求,要將圖3的結果變成圖2的結果,也就是順時針旋轉90度,仍然以c和name作爲字段名。也許方法很多,但SQL Server2005提供了一個unpivot函數,該函數是pivot函數的逆過程。也就是將記錄集順時針旋轉90度,先看下面的SQL語句:
declare @t table(name varchar(20))
insert @t
select 'abc' union all
select 'xxx' union all
select 'xxx' union all
select 'ttt'
;
with tt as(
select * from @t pivot(count(name) for name in([abc] ,[ttt],[xxx])) p)
select * from tt

    上面的SQL語句將輸出如圖3所示的結果。如果將最後一條SQL語句(select * from tt)換成如下的SQL語句,將輸出如圖2所示的結果。

select * from tt  unpivot([c] for name in([abc] ,[xxx],[ttt])) p

    要注意的是,[c]中的c表示聚合結果列的字段名,name表示要聚合列的字段名,這兩個值可以是任意滿足字段名命名規則的字符串, [abc] ,[xxx],[ttt]分別是圖3所示的記錄集的字段名,這些值必須一致。執行下面的SQL語句將獲得圖4的輸出結果。

select * from tt  unpivot([統計值] for 統計名 in([abc] ,[xxx],[ttt])) p

4

《銀河系列原創教程》發佈
《Java Web開發速學寶典》出版,歡迎定購
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章