1. 程式人生 > >SQL Server 2008中增強的彙總技巧

SQL Server 2008中增強的彙總技巧

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

SQL Server 2008中SQL應用系列--目錄索引


SQL Server 2008中對彙總有明顯的增強,有點像Oracle的語法了。請看下面五個例子:

假定場景如下:某幾位員工在不同時間參加了不同的專案,獲取了相應的收入,現在需要按各種分類進行統計。

基本表如下:

USE testDb2GOIF NOT OBJECT_ID('tb_Income') IS NULLDROP TABLE [tb_Income]/****** Object: Table [dbo].[tb_Income] Script Date: 2012/4/5 8:19:21 ******/CREATE TABLE [dbo].[tb_Income]([TeamID] int not null,[PName] [Nvarchar](20) NOT NULL,[CYear] Smallint NOT NULL,[CMonth] TinyInt NOT NULL,[CMoney] Decimal
(10,2) Not Null)GOINSERT [dbo].[tb_Income]SELECT 1,'胡一刀',2011,2,5600union ALL SELECT 1,'胡一刀',2011,1,5678union ALL SELECT 1,'胡一刀',2011,3,6798union ALL SELECT 2,'胡一刀',2011,4,7800union ALL SELECT 2,'胡一刀',2011,5,8899union ALL SELECT 3,'胡一刀',2012,8,8877union ALL SELECT 1,'苗人鳳',2011,1,3455union ALL SELECT 1,'苗人鳳',2011
,2,4567union ALL SELECT 2,'苗人鳳',2011,3,5676union ALL SELECT 3,'苗人鳳',2011,4,5600union ALL SELECT 2,'苗人鳳',2011,5,6788union ALL SELECT 2,'苗人鳳',2012,6,5679union ALL SELECT 2,'苗人鳳',2012,7,6785union ALL SELECT 2,'張無忌',2011,2,5600union ALL SELECT 2,'張無忌',2011,3,2345union ALL SELECT 2,'張無忌',2011,5,12000union ALL SELECT 3,'張無忌',2011,4,23456union ALL SELECT 3,'張無忌',2011,6,4567union ALL SELECT 1,'張無忌',2012,7,6789union ALL SELECT 1,'張無忌',2012,8,9998union ALL SELECT 3,'趙半山',2011,7,6798union ALL SELECT 3,'趙半山',2011,10,10000union ALL SELECT 3,'趙半山',2011,9,12021union ALL SELECT 2,'趙半山',2012,11,8799union ALL SELECT 1,'趙半山',2012,12,10002union ALL SELECT 3,'令狐沖',2011,8,7896union ALL SELECT 3,'令狐沖',2011,9,7890union ALL SELECT 2,'令狐沖',2011,10,7799union ALL SELECT 2,'令狐沖',2011,11,9988union ALL SELECT 2,'令狐沖',2012,9,34567union ALL SELECT 3,'令狐沖',2012,12,5609GO 

資料如下:

SELECT * FROM tb_Income/*TeamID PName CYear CMonth CMoney1 胡一刀 2011 2 5600.001 胡一刀 2011 1 5678.001 胡一刀 2011 3 6798.002 胡一刀 2011 4 7800.002 胡一刀 2011 5 8899.003 胡一刀 2012 8 8877.001 苗人鳳 2011 1 3455.001 苗人鳳 2011 2 4567.002 苗人鳳 2011 3 5676.003 苗人鳳 2011 4 5600.002 苗人鳳 2011 5 6788.002 苗人鳳 2012 6 5679.002 苗人鳳 2012 7 6785.002 張無忌 2011 2 5600.002 張無忌 2011 3 2345.002 張無忌 2011 5 12000.003 張無忌 2011 4 23456.003 張無忌 2011 6 4567.001 張無忌 2012 7 6789.001 張無忌 2012 8 9998.003 趙半山 2011 7 6798.003 趙半山 2011 10 10000.003 趙半山 2011 9 12021.002 趙半山 2012 11 8799.001 趙半山 2012 12 10002.003 令狐沖 2011 8 7896.003 令狐沖 2011 9 7890.002 令狐沖 2011 10 7799.002 令狐沖 2011 11 9988.002 令狐沖 2012 9 34567.003 令狐沖 2012 12 5609.00*/ 
 

一、使用CUBE彙總資料(http://msdn.microsoft.com/en-us/library/bb522495%28v=sql.105%29.aspx

小試牛刀,

/*********使用CUBE彙總資料***************//********* [email protected] 邀月***************/SELECT TeamID as 小組ID,SUM(CMoney) 總收入FROM tb_IncomeGROUP BY CUBE (TeamID)----ORDER BY TeamID desc
邀月工作室

改進查詢:

SELECT TeamID as 小組ID,PName as 姓名,SUM(CMoney) 總收入FROM tb_IncomeGROUP BY CUBE (TeamID,PName)
邀月工作室

 二、使用ROLLUP彙總資料(http://msdn.microsoft.com/en-us/library/bb522495%28v=sql.105%29.aspx

 

/*********使用ROLLUP彙總資料***************//********* [email protected] 邀月***************/SELECT TeamID as 小組ID,PName as 姓名,SUM(CMoney) 總收入FROM tb_IncomeGROUP BY ROLLUP (TeamID,PName)
邀月工作室

 注意:使用Rollup與指定的聚合列的順序有關。


三、使用Grouping Sets建立自定義彙總資料(http://msdn.microsoft.com/en-us/library/bb522495%28v=sql.105%29.aspx

 除了Cube和Rollup,還有更加靈活強大的自定義集合彙總--Grouping Sets


/*********使用Grouping Sets建立自定義彙總資料***************//********* 3[email protected] 邀月***************/SELECT TeamID as 小組ID,PName as 姓名,CYear as 年份,----min(CMonth) as 月份,SUM(CMoney) 總收入FROM tb_IncomeWhere CMonth=2GROUP BY grouping SETS ((TeamID),(TeamID,PName),(CYear,PName))


邀月工作室

四、使用Grouping標識彙總行(http://technet.microsoft.com/zh-cn/library/ms178544.aspx

 細心的朋友可能會注意到,如果Cube後有兩個以上的彙總列時,可能會有一些列是Null,那麼這些Null值究竟本身就是Null,還是由於聚合產生的Null呢,此時,Grouping函式大顯身手的機會來了。

/*********使用Grouping標識彙總行***************//********* [email protected] 邀月***************/SELECT TeamID as 小組ID,CYear as 年份,CASE WHEN grouping(TeamID)=0 AND grouping(CYear)=1 THEN '小組彙總'WHEN grouping(TeamID)=1 AND grouping(CYear)=0 THEN '年份彙總'WHEN grouping(TeamID)=1 AND grouping(CYear)=1 THEN '所有彙總'else '正常行' END as 行類別,SUM(CMoney) 總收入FROM tb_IncomeGROUP BY CUBE (TeamID,CYear)

邀月工作室

至此,如果還有美中不足的話,那就是分組還是有點凌亂,下面我們將隆重推出終極武器--Grouping_ID,它與Grouping類似,但提供更為精細的顆粒度,以確認分組級別,當然使用也更為複雜,請看下面的示例:

五、使用Grouping_ID標識分組級別(http://technet.microsoft.com/zh-cn/library/bb510624.aspx

為了更清楚地說明問題,我們需要修改一下表結構,增加一個欄位--專案所在的地點(AreaID),如下:

/*************修改表結構***************************/ALTER table tb_Income add AreaID int nullGOupdate tb_Income SET AreaID=TeamID+CMonth%5+CYear%2GO

此時資料變成這樣:
SELECT * FROM tb_Income/*TeamID    PName    CYear    CMonth    CMoney    AreaID    胡一刀    2011    2    5600.00    4    胡一刀    2011    1    5678.00    3    胡一刀    2011    3    6798.00    5    胡一刀    2011    4    7800.00    7    胡一刀    2011    5    8899.00    3    胡一刀    2012    8    8877.00    6    苗人鳳    2011    1    3455.00    3    苗人鳳    2011    2    4567.00    4    苗人鳳    2011    3    5676.00    6    苗人鳳    2011    4    5600.00    8    苗人鳳    2011    5    6788.00    3    苗人鳳    2012    6    5679.00    3    苗人鳳    2012    7    6785.00    4    張無忌    2011    2    5600.00    5    張無忌    2011    3    2345.00    6    張無忌    2011    5    12000.00    3    張無忌    2011    4    23456.00    8    張無忌    2011    6    4567.00    5    張無忌    2012    7    6789.00    3    張無忌    2012    8    9998.00    4    趙半山    2011    7    6798.00    6    趙半山    2011    10    10000.00    4    趙半山    2011    9    12021.00    8    趙半山    2012    11    8799.00    3    趙半山    2012    12    10002.00    3    令狐沖    2011    8    7896.00    7    令狐沖    2011    9    7890.00    8    令狐沖    2011    10    7799.00    3    令狐沖    2011    11    9988.00    4    令狐沖    2012    9    34567.00    6    令狐沖    2012    12    5609.00    5*/

我們需要統計小組、地區、月份三個維度的彙總資料。
/*********使用Grouping_ID標識分組級別***************//*********  [email protected]  邀月***************/SELECT TeamID as 小組ID,AreaID as 地點ID,CMonth as 月份,SUM(CMoney) 總收入FROM tb_Income Where AreaID IN (3,5,6,7,8,9,2,4) AND CYear =2011  AND CMonth=2GROUP BY CUBE (TeamID,AreaID,CMonth)----ORDER  BY TeamID,AreaID,CMonth

統計結果:

邀月工作室

我們注意到,由於維度從兩個變成三個,此時資料比較凌亂,即使排序也不能有效解決。幸好,我們有Grouping_ID。看下例:

SELECT TeamID as 小組ID,AreaID as 地點ID,CMonth as 月份,CASE grouping_ID(TeamID,AreaID,CMonth) WHEN 1 THEN '小組/地點彙總' WHEN 2 THEN '小組/月份彙總' WHEN 3 THEN '小組彙總' WHEN 4 THEN '地點/月份彙總' WHEN 5 THEN '地點彙總' WHEN 6 THEN '月份彙總' WHEN 7 THEN '所有彙總' else '正常行' END as 行類別,SUM(CMoney) 總收入FROM tb_Income Where AreaID IN (3,5,6,7,8,9,2,4) AND CYear =2011  AND CMonth=2GROUP BY CUBE (TeamID,AreaID,CMonth)----ORDER  BY TeamID,AreaID,CMonth

注意:程式碼中新增的部分,這裡需要稍微解釋一下,Grouping_ID接受幾個輸入列,返回二進位制列列表計算的整數值,你可以把這三個維度,看作是(0,1,1)、(0,1,0)這樣類似的二進位制,而Grouping_ID負責將運算結果以整數形式返回。

效果:

邀月工作室

至此,Group By的彙總暫時告一段落,希望您不虛此行,有所斬獲!


小結:帶有Cube,Rollup,grouping Sets的Group By函式在統計與分析中有著廣泛的應用,相信它的高效簡捷,在特定的場合會令人你愛不釋手!


邀月注:本文版權由邀月和CSDN共同所有,轉載請註明出處。
助人等於自助!   [email protected]



           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述