SQL Server 2008中對彙總有明顯的增強,可以說基本上很像Oracle的文法了。請看下面五個例子:
基本表如下:
- USE testDb2
- GO
- IF NOT OBJECT_ID('tb_Income') IS NULL
- DROP TABLE [tb_Income]
- 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
- )
- GO
- INSERT [dbo].[tb_Income]
- SELECT 1,'胡一刀',2011,2,5600
- union ALL SELECT 1,'胡一刀',2011,1,5678
- union ALL SELECT 1,'胡一刀',2011,3,6798
- union ALL SELECT 2,'胡一刀',2011,4,7800
- union ALL SELECT 2,'胡一刀',2011,5,8899
- union ALL SELECT 3,'胡一刀',2012,8,8877
- union ALL SELECT 1,'苗人鳳',2011,1,3455
- union ALL SELECT 1,'苗人鳳',2011,2,4567
- union ALL SELECT 2,'苗人鳳',2011,3,5676
- union ALL SELECT 3,'苗人鳳',2011,4,5600
- union ALL SELECT 2,'苗人鳳',2011,5,6788
- union ALL SELECT 2,'苗人鳳',2012,6,5679
- union ALL SELECT 2,'苗人鳳',2012,7,6785
- union ALL SELECT 2,'張無忌',2011,2,5600
- union ALL SELECT 2,'張無忌',2011,3,2345
- union ALL SELECT 2,'張無忌',2011,5,12000
- union ALL SELECT 3,'張無忌',2011,4,23456
- union ALL SELECT 3,'張無忌',2011,6,4567
- union ALL SELECT 1,'張無忌',2012,7,6789
- union ALL SELECT 1,'張無忌',2012,8,9998
- union ALL SELECT 3,'趙半山',2011,7,6798
- union ALL SELECT 3,'趙半山',2011,10,10000
- union ALL SELECT 3,'趙半山',2011,9,12021
- union ALL SELECT 2,'趙半山',2012,11,8799
- union ALL SELECT 1,'趙半山',2012,12,10002
- union ALL SELECT 3,'令狐沖',2011,8,7896
- union ALL SELECT 3,'令狐沖',2011,9,7890
- union ALL SELECT 2,'令狐沖',2011,10,7799
- union ALL SELECT 2,'令狐沖',2011,11,9988
- union ALL SELECT 2,'令狐沖',2012,9,34567
- union ALL SELECT 3,'令狐沖',2012,12,5609
- GO
資料如下:
[sql] view plain copy print ?
- SELECT * FROM tb_Income
一、使用CUBE彙總資料(http://msdn.microsoft.com/en-us/library/bb522495%28v=sql.105%29.aspx)
- SELECT TeamID as 小組ID,
- SUM(CMoney) 總收入
- FROM tb_Income
- GROUP BY CUBE (TeamID)
- ----ORDER BY TeamID desc
增加彙總:
- SELECT TeamID as 小組ID,PName as 姓名,
- SUM(CMoney) 總收入
- FROM tb_Income
- GROUP BY CUBE (TeamID,PName)
二、使用ROLLUP彙總資料(http://msdn.microsoft.com/en-us/library/bb522495%28v=sql.105%29.aspx)
- SELECT TeamID as 小組ID,PName as 姓名,
- SUM(CMoney) 總收入
- FROM tb_Income
- GROUP BY ROLLUP (TeamID,PName)
注意:使用Rollup與指定的聚合列的順序有關。
三、使用Grouping Sets建立自定義彙總資料(http://msdn.microsoft.com/en-us/library/bb522495%28v=sql.105%29.aspx)
- SELECT TeamID as 小組ID,PName as 姓名,CYear as 年份,----min(CMonth) as 月份,
- SUM(CMoney) 總收入
- FROM tb_Income
- Where CMonth=2
- GROUP BY grouping SETS ((TeamID),(TeamID,PName),(CYear,PName))
四、使用Grouping辨別彙總行(http://technet.microsoft.com/zh-cn/library/ms178544.aspx)
細心的朋友可能會注意到,如果Cube後有兩個以上的彙總列時,可能會有一些列是Null,那麼這些Null值究竟本身就是Null,還是由于聚合産生的Null呢,此時,Grouping函數大顯身手的機會來了。
- 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_Income
- GROUP BY CUBE (TeamID,CYear)
五、使用Grouping_ID辨別分組級别(http://technet.microsoft.com/zh-cn/library/bb510624.aspx)--多元資料彙總的終極利器!!!
為了更清楚地說明問題,我們需要修改一下表結構,增加一個字段--項目所在的地點(AreaID),如下:
- ALTER table tb_Income
- add AreaID int null
- GO
- update tb_Income SET AreaID=TeamID+CMonth%5+CYear%2
- GO
此時資料變成這樣:
- SELECT * FROM tb_Income
我們需要統計小組、地區、月份三個次元的彙總資料。
- 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=2
- GROUP 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=2
- GROUP BY CUBE (TeamID,AreaID,CMonth)
- ----ORDER BY TeamID,AreaID,CMonth
注意:代碼中新增的部分,這裡需要稍微解釋一下,Grouping_ID接受幾個輸入列,傳回二進制列清單計算的整數值,你可以把這三個次元,看作是(0,1,1)、(0,1,0)這樣類似的二進制,而Grouping_ID負責将運算結果以整數形式傳回。
效果: