SQL Server 2008中增强的汇总技巧

SQL Server 2008中增强的汇总技巧

SQL Server 2008中SQL应用系列--目录索引

SQL Server 2008中对汇总有明显的增强,有点像Oracle的语法了。请看下面五个例子:

假定场景如下:某几位员工在不同时间参加了不同的项目,获取了相应的收入,现在需要按各种分类进行统计。

基本表如下:

USE testDb2 GOIF NOT OBJECT_ID(‘tb_Income‘) IS NULL DROP 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)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,8877union 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,6785union 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,9998union 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,10002union 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,5609GO

数据如下:

SELECT * FROM tb_Income/*TeamID PName CYear CMonth CMoney 1 胡一刀 2011 2 5600.00 1 胡一刀 2011 1 5678.00 1 胡一刀 2011 3 6798.00 2 胡一刀 2011 4 7800.00 2 胡一刀 2011 5 8899.00 3 胡一刀 2012 8 8877.00 1 苗人凤 2011 1 3455.00 1 苗人凤 2011 2 4567.00 2 苗人凤 2011 3 5676.00 3 苗人凤 2011 4 5600.00 2 苗人凤 2011 5 6788.00 2 苗人凤 2012 6 5679.00 2 苗人凤 2012 7 6785.00 2 张无忌 2011 2 5600.00 2 张无忌 2011 3 2345.00 2 张无忌 2011 5 12000.00 3 张无忌 2011 4 23456.00 3 张无忌 2011 6 4567.00 1 张无忌 2012 7 6789.00 1 张无忌 2012 8 9998.00 3 赵半山 2011 7 6798.00 3 赵半山 2011 10 10000.00 3 赵半山 2011 9 12021.00 2 赵半山 2012 11 8799.00 1 赵半山 2012 12 10002.00 3 令狐冲 2011 8 7896.00 3 令狐冲 2011 9 7890.00 2 令狐冲 2011 10 7799.00 2 令狐冲 2011 11 9988.00 2 令狐冲 2012 9 34567.00 3 令狐冲 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_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

/*********使用ROLLUP汇总数据***************//********* [email protected] 邀月***************/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

除了Cube和Rollup,还有更加灵活强大的自定义集合汇总--Grouping Sets

/*********使用Grouping Sets创建自定义汇总数据***************//********* [email protected] 邀月***************/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函数大显身手的机会来了。

/*********使用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_Income GROUP 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%2 GO

此时数据变成这样:

SELECT * FROM tb_Income/* TeamID    PName    CYear    CMonth    CMoney    AreaID 1    胡一刀    2011    2    5600.00    4 1    胡一刀    2011    1    5678.00    3 1    胡一刀    2011    3    6798.00    5 2    胡一刀    2011    4    7800.00    7 2    胡一刀    2011    5    8899.00    3 3    胡一刀    2012    8    8877.00    6 1    苗人凤    2011    1    3455.00    3 1    苗人凤    2011    2    4567.00    4 2    苗人凤    2011    3    5676.00    6 3    苗人凤    2011    4    5600.00    8 2    苗人凤    2011    5    6788.00    3 2    苗人凤    2012    6    5679.00    3 2    苗人凤    2012    7    6785.00    4 2    张无忌    2011    2    5600.00    5 2    张无忌    2011    3    2345.00    6 2    张无忌    2011    5    12000.00    3 3    张无忌    2011    4    23456.00    8 3    张无忌    2011    6    4567.00    5 1    张无忌    2012    7    6789.00    3 1    张无忌    2012    8    9998.00    4 3    赵半山    2011    7    6798.00    6 3    赵半山    2011    10    10000.00    4 3    赵半山    2011    9    12021.00    8 2    赵半山    2012    11    8799.00    3 1    赵半山    2012    12    10002.00    3 3    令狐冲    2011    8    7896.00    7 3    令狐冲    2011    9    7890.00    8 2    令狐冲    2011    10    7799.00    3 2    令狐冲    2011    11    9988.00    4 2    令狐冲    2012    9    34567.00    6 3    令狐冲    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=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负责将运算结果以整数形式返回。

效果:


至此,Group By的汇总暂时告一段落,希望您不虚此行,有所斩获!

小结:带有Cube,Rollup,grouping Sets的Group By函数在统计与分析中有着广泛的应用,相信它的高效简捷,在特定的场合会令你爱不释手!

时间: 2024-10-04 16:36:38

SQL Server 2008中增强的汇总技巧的相关文章

SQL Server 2008中SQL增强之一:Values新用途

SQL Server 2008中新增功能:可以使用单个Insert命令插入多行. Create table Demo_Values (PKID int not null identity(1,1) primary key ,DName Nvarchar(20) null ,DCode NVarchar(30) null ,DDate datetime null ) go--this SQL is only for SQL Server 2008 Insert into Demo_Values (

在windows 2008 R2中SQl Server 2008中代理启动失败的一个原因总结

启动SQL代理的时候报错如下: 关调用实时(JIT)调试而不是此对话框的详细信息,请参见此消息的结尾. ************** 异常文本 **************System.NullReferenceException: 未将对象引用设置到对象的实例. Server stack trace: 在 Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer.ObjectExplorer.FindObjectExplore

【转载】SQL Server 2008 中新建用户登录并指定该用户的数据库

提要:我在 SQL Server 中新建用户登录时,出现了三种错误,错误代码分别是 18456.15128.4064 -----------------------------------  正 文 ----------------------------------- 一.实验环境 Windows 7SQL Server 2008数据库实例名为 TestDB,新建的用户名为 testUser 二.操作步骤 1.打开 SQL Server Management Studio,以 Windows身

使用变量向SQL Server 2008中插入数据

QT通过ODBC连接数据库SQL Server 2008,进行数据插入时遇到的问题: 先把数据存入变量中,如何使用变量进行插入?插入语句该怎么写? QSqlQuery query(db); query.exec("insert into device values('"+datetime+"','"+splantNum+"','"+sdeviceNum+"','"+stemper+"','"+spress+

SQL SERVER 2008中使用VARBINARY(MAX)进行图像存取的实现方法

在数据库应用项目开发中,经常会使用一些二进制的图像数据,存储和读取显示图像数据主要采用的是路径链接法和内存流法.路径链接法是将图像文件保存在固定的路径下,数据库中只存储图像文件的路径和名称,此方法数据库容量小,存取速度快,但安全性较差:内存流法是将二进制数据直接存储在数据库中,此方法对数据的共享非常方便,安全性相对较高,常用于图像容量不是很大的时候. 本文主要讨论通过SQL Server 2008使用内存流法如何实现二进制图像数据的存储. 1 VARBINARY(MAX)数据类型简介 在SQL

在SQL Server 2008中调用.net,dll

T-SQL的在执行普通的查询的时候是很高效的,但是在执行循环,判断这样的语句的时候效率就不那么的高了.这时可以借助CLR了,我们可以在SQL Server 2008中扩展C#程序来完成循环等过程式的查询,或者其他SQL不便实现的功能.这个随笔中将介绍在SQL Server中扩展C#程序实现正则表达式的替换功能. 新建一个类库程序命名为Regex,打开Visual Studio 2008,点击File,点击New,点击Project,在弹出的New Project对话框中选择Class Libra

SQL Server 2008中的9种数据挖掘算法

1.决策树算法 决策树,又称判定树,是一种类似二叉树或多叉树的树结构.决策树是用样本的属性作为结点,用属性的取值作为分支,也就是类似流程图的过程,其中每个内部节点表示在一个属性上的测试,每个分支代表一个测试输出,而每个树叶节点代表类或类分布.它对大量样本的属性进行分析和归纳.根结点是所有样本中信息量最大的属性,中间结点是以该结点为根的子树所包含的样本子集中信息量最大的属性,决策树的叶结点是样本的类别值. 从树的根结点出发,将测试条件用于检验记录,根据测试结果选择适当的分支,沿着该分支或者达到另一

利用Ring Buffer在SQL Server 2008中进行连接故障排除

原文:利用Ring Buffer在SQL Server 2008中进行连接故障排除 出自:http://blogs.msdn.com/b/apgcdsd/archive/2011/11/21/ring-buffer-sql-server-2008.aspx SQL Server 2008中包含一个新功能,旨在帮助解决特别棘手的连接问题.这个新功能是Connectivity Ring Buffer,它可以捕捉每一个由服务器发起的连接关闭记录(server-initiated connection

SQL Server 2008中的数据压缩

SQL Server 2008中引入了数据压缩的功能,允许在表.索引和分区中执行数据压缩.这样不仅可以大大节省磁盘的占用空间,还允许将更多数据页装入内存中,从而降低磁 盘IO,提升查询的性能.当然,凡事有利有弊,在启用数据压缩后,数据库服务器就需要额外的CPU资源来进行压缩处理.一般说来,数据库服务器的CPU占 用率不会太高,而磁盘IO容易成为瓶颈,所以在大多数情况下对大数据库特别是数据仓库启用该项功能还是利大于弊.SQL Server 2008的数据压缩分为行压缩和页压缩两种.行压缩主要是通过