SQL Server 2008中增强的汇总技巧

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

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

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

基本表如下:

View Code

数据如下:

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汇总数据***************/

/********* 3w@live.cn 邀月***************/
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汇总数据***************/

/********* 3w@live.cn 邀月***************/

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创建自定义汇总数据***************/

/********* 3w@live.cn 邀月***************/

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标识汇总行***************/

/********* 3w@live.cn 邀月***************/
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 null

GO

update 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标识分组级别***************/

/********* 3w@live.cn 邀月***************/

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函数在统计与分析中有着广泛的应用,相信它的高效简捷,在特定的场合会令你爱不释手!

邀月注:本文版权由邀月和博客园共同所有,转载请注明出处。
助人等于自助!  3w@live.cn

SQL Server 2008 Tips

 
摘要: SQL Server 2008 新增参数类型-表值参数。使用用户定义的表类型来声明,借助它,可以不必创建临时表或许多参数,即可向存储过程发送多行数据。对于某些繁忙的系统,这减少了应用程序和数据库服务器之间的交互,从而减少了占用的带宽,数据库端的事务处理更高效。阅读全文
posted @ 2012-04-06 13:07 邀月 阅读(22) | 评论 (0) 编辑
 
摘要: SQL Server 2008中对汇总有明显的增强,有点像Oracle的语法了。请看下面四个例子:假定场景如下:某几位员工在不同时间参加了不同的项目,获取了相应的收入,现在需要按各种分类进行统计。阅读全文
posted @ 2012-04-06 01:22 邀月 阅读(1785) | 评论 (28) 编辑
 
摘要: 今天给新成员讲解PIVOT 和 UNPIVOT示例,顺便整理了一下的用法。这是自SQL Server 2005起提供的新功能。官方示例:http://msdn.microsoft.com/zh-cn/library/ms177410%28v=sql.105%29.aspx阅读全文
posted @ 2012-04-05 18:52 邀月 阅读(124) | 评论 (0) 编辑
 
摘要:   安装SQL Server 2008反复提示需要安装MICROSOFT .NET FRAMEWORK 3.5 SP1的一个解决办法阅读全文
posted @ 2011-08-31 17:30 邀月 阅读(2289) | 评论 (5) 编辑
 
摘要: 最近有些忙,今天看到微软已经在7月11日发布Microsoft® SQL Server® 2008 R2 Service Pack 1正式版,下载地址为: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=26727 包含中文版,版本号为10.50.2500.0,关于本SP1修复的bug列表,请查看:http://support.microsoft.com/kb/2528583阅读全文
posted @ 2011-07-21 14:21 邀月 阅读(1136) | 评论 (0) 编辑
 
摘要: Service Broker的事件通知   事件通知是集成到Service Broker的功能,使用它可以在SQL Server实例中异步捕捉SQL事件,将事件消息路由到特定的队列中。只需最小的系统开销,就可以跟踪发生在SQL Server实例中的事件,比如用户登录、存储过程编译、权限修改、对象处理(例如对数据库、程序集、角色或表的Create/Alter/Drop事件)。   [重要说明]:事件通知功能与SQL Trace相似,不同之处在于,它是异步的,并且对SQL Server实例整体性能影响最小。阅读全文
posted @ 2011-05-06 10:56 邀月 阅读(475) | 评论 (1) 编辑
 
摘要: 上文演示了在同一个SQL Server实例的不同数据库之间实现Service Broker,其实,更常见的是在不同的SQL Server实例之间进行通信,本文将通过实例演示如何进行Service Broker远程通信。 以下是实现远程Service Broker的基本步骤: 一、启用传输安全 二、启用对话安全 三、创建路由 四、创建远程服务绑定阅读全文
posted @ 2011-05-05 16:29 邀月 阅读(1758) | 评论 (8) 编辑
 
摘要: SSIS导入IIS日志的简单步骤。阅读全文
posted @ 2011-05-03 22:34 邀月 阅读(553) | 评论 (3) 编辑
 
摘要: 一个Excel导入SQL server的例子,分别使用游标、CTE、master..spt_values实现。阅读全文
posted @ 2011-05-02 19:30 邀月 阅读(3161) | 评论 (14) 编辑
 
摘要: 导读:除了利用office提供的API对word文档内容进行检索外,本文简要总结如何结合SQL Server的全文检索技术对Word文件的内容进行检索的三个方案。阅读全文
posted @ 2011-04-21 23:00 邀月 阅读(1965) | 评论 (12) 编辑
 
摘要: 在《安装VS2010 SP1后SQL Server 2008 r2智能感知功能(IntelliSense)失效!》一文中,我们知道,安装vs 2010 sp1后,Sql server 2008 r2 RTM的智能感知失效,微软已经Fix了这个问题,并将会在2011年4月中旬发布“Cumulative Update #7 for SQL Server 2008 R2 RTM”以修正这个Bug,请关注更新站点(http://blogs.msdn.com/b/sqlreleaseservices/)。今天看到一个替代的方案。阅读全文
posted @ 2011-04-15 11:18 邀月 阅读(1757) | 评论 (7) 编辑
 
摘要: 导读:在上篇《SQL Server 2008中Service Broker基础应用(上)》中,简要介绍了Service Broker的一般步骤,本文继续介绍Service Broker的设置会话优先级,存储过程中实现。阅读全文
posted @ 2011-04-12 10:14 邀月 阅读(531) | 评论 (2) 编辑
 
摘要: 导读:本文主要涉及Service Broker的基本概念及建立一个Service Broker应用程序的基本步骤。阅读全文
posted @ 2011-04-05 16:26 邀月 阅读(2402) | 评论 (4) 编辑
 
摘要: SQL Server 2008引入透明数据加密(Transparent Data Encryption),即TDE,它允许你完全无需修改应用程序代码而对整个数据库加密。当一个用户数据库可用且已启用TDE时,在写入到磁盘时在页级实现加密。在数据页读入内存时解密。如果数据库文件或数据库备份被盗,没有用来加密的原始证书将无法访问。这几乎是SQL Server2008安全选项中最激动人心的功能了,有了它,我们至少可以将一些初级的恶意窥视拒之见外。阅读全文
posted @ 2011-03-17 16:00 邀月 阅读(1580) | 评论 (5) 编辑
 
摘要: 证书可以在数据库中加密和解密数据。证书包含密钥对、关于证书拥有者的信息、证书可用的开始和结束过期日期。证书同时包含公钥和密钥,前者用来加密,后者解密。SQL Server可以生成它自己的证书,也可以从外部文件或程序集载入。因为可以备份然后从文件中载入它们,证书比非对称密钥更易于移植,而非对称密钥却做不到。这意味着可以在数据库中方便地重用同一个证书。阅读全文
posted @ 2011-03-15 22:49 邀月 阅读(1495) | 评论 (14) 编辑
 
摘要: 证书和非对称密钥使用数据库级的内部公钥加密数据,并且使用数据库级内部私钥解密数据。而对称密钥相对简单,它们包含一个同时用来加密和解密的密钥。困此,使用对称密钥加密数据更快,并且用在大数据时更加合适。尽管复杂度是考虑使用它的因素,但它仍然是一个很好的加密数据的选择。阅读全文
posted @ 2011-03-15 00:09 邀月 阅读(1472) | 评论 (13) 编辑
 
摘要: 非对称密钥包含数据库级的内部公钥和私钥,它可以用来加密和解密SQL Server数据库中的数据,它可以从外部文件或程序集中导入,也可以在SQL Server数据库中生成。它不像证书,不可以备份到文件。这意味着一旦在SQL Server中创建了它,没有非常简单的方法在其他用户数据库中重用相同的密钥。非对称密钥对于数据库加密属于高安全选项,因而需要更多的SQL Server资源。阅读全文
posted @ 2011-03-14 05:59 邀月 阅读(1611) | 评论 (0) 编辑
 
摘要: SQL Server 2008中的一些特性总结及BI学习笔记系列,欢迎与邀月交流。3w@live.cn阅读全文
posted @ 2011-03-10 21:00 邀月 阅读(11979) | 评论 (21) 编辑
 
摘要: 在SQL Server中的加密由层次结构形式进行处理以提供多级别的安全。SQL Server包含两个用于加密数据的密钥类型。阅读全文
posted @ 2011-03-10 14:27 邀月 阅读(2174) | 评论 (12) 编辑
 
摘要: 在用powerdesigner逆向工程生成PDM时,列注释(ColumnComment)始终无法生成,历经数小时的探索,找到一个折衷的方法,现分享如下。并希望有高手指点更好的方法。 邀月使用的是Powerdesigner 15.2,数据库为SQL Server 2008 r2阅读全文
posted @ 2011-03-04 21:39 邀月 阅读(2918) | 评论 (3) 编辑
 
摘要: 导读:本文主要涉及EncryptByPassPhrase和DecryptByPassPhrase函数进行通行短语(PassPhrase)加密。阅读全文
posted @ 2011-03-03 08:05 邀月 阅读(1527) | 评论 (0) 编辑
 
摘要: 最近看到一个SQL Server的小例子,发现完全可以作为SQL server的一道入门面试题。题目如下: 例:有一合同表Contract Id Name Total buget 1 合同名称 100 102,22 2 合同名称2 300 ,102,22, 3 合同名称3 200 ,103,23, 要求:用SQL语句更新表的buget字段,如果前后没有","要加上","(即一个英文逗号)。(10分)阅读全文
posted @ 2011-03-02 09:48 邀月 阅读(712) | 评论 (5) 编辑
 
摘要: 本文主要 涉及DDL触发器和登录触发器的应用实例。MicrosoftSQL Server 提供两种主要机制来强制使用业务规则和数据完整性:约束和触发器。触发器为特殊类型的存储过程,可在执行语言事件时自动生效。SQL Server 包括三种常规类型的触发器:DML 触发器、DDL 触发器和登录触发器。阅读全文
posted @ 2011-03-01 15:05 邀月 阅读(1835) | 评论 (5) 编辑
 
摘要: 最近对SQL Server 2008的安全入门略作小结,以作备忘。本文涉及两个应用:存储过程加密和安全上下文。阅读全文
posted @ 2011-02-28 14:37 邀月 阅读(2379) | 评论 (11) 编辑
 
摘要: 当一个用户会话(会话1)已经落定了一个资源,而另一个会话(会话2)想要修改该资源,并且会话2也锁定了会话1想要修改的资源时,就会出现“死锁”(deadlocking)。在另一方释放资源前,会话1和会话2都不可能继续。所以,SQL Server会选择死锁中的一个会话作为“死锁牺牲品”。阅读全文
posted @ 2011-02-27 18:06 邀月 阅读(2065) | 评论 (8) 编辑
 
摘要: 当一个数据库会话中的事务正锁定一个或多个其他会话事务想要读取或修改的资源时,会产生阻塞(Blocking)。通常短时间的阻塞没有问题,且是较忙的应用程序所需要的。然而,设计糟糕的应用程序会导致长时间的阻塞,这就不必要地锁定了资源,而且阻塞了其他会话读取和更新它们。阅读全文
posted @ 2011-02-18 15:48 邀月 阅读(1354) | 评论 (0) 编辑
 
摘要: 锁定(Locking)是一个关系型数据库系统的常规和必要的一部分,它防止对相同数据作并发更新或在更新过程中查看数据,从而保证被更新数据的完整性。它也能防止用户读取正在被修改的数据。Sql Server动态地管理锁定,然而,还是很有必要了解Transact-SQL查询如何影响SQL Server中的锁定。SQL Server 2008带来了新的表选项,可以禁用锁升级或在分区(而不是表)范围启用锁升级。阅读全文
posted @ 2011-02-18 12:37 邀月 阅读(1610) | 评论 (0) 编辑
 
摘要: 无论是有意无意,如果事务在数据库中保持打开,则它会阻塞其他进程对修改后的数据进行操作。同样,对事务日志进行备份也只会截断不活动事务的那部分事务日志,所以打开的事务会导致日志变多(甚至达到物理限制),直到事务被提交或回滚。 要找到最早的活动事务,可以使用DBCC OPENTRAN命令。阅读全文
posted @ 2010-12-24 15:06 邀月 阅读(760) | 评论 (4) 编辑
 
摘要: 在SQL Server 2005以上版本中,在一个增强的WaitFor命令,其作用可以和一个job相当。但使用更加简捷。阅读全文
posted @ 2010-12-07 16:55 邀月 阅读(1246) | 评论 (5) 编辑
 
摘要: SQL Server 2008提供了一个增强的SQL命令,用法参看MSDN:http://msdn.microsoft.com/zh-cn/library/bb510625.aspx 功能:根据与源表联接的结果,对目标表执行插入、更新或删除操作。例如,根据在另一个表中找到的差异在一个表中插入、更新或删除行,可以对两个表进行同步。阅读全文
posted @ 2010-10-17 21:51 邀月 阅读(2556) | 评论 (5) 编辑
 
摘要: 一、TOP替代Set RowCount 在SQL Server 2005之前的传统SQL语句中,top语句是不支持局部变量的。见http://www.cnblogs.com/downmoon/archive/2007/12/29/1019686.html 此时可以使用Set RowCount,但是在SQL Server 2005/2008中,TOP通常执行得更快,所以应该用TOP关键字来取代Set RowCount。阅读全文
posted @ 2010-10-12 22:27 邀月 阅读(1987) | 评论 (4) 编辑
 
摘要: SQL Server 2008中新增功能:可以使用单个Insert命令插入多行。阅读全文
posted @ 2010-10-12 20:51 邀月 阅读(2241) | 评论 (15) 编辑
 
摘要: 微软从SQl2005起引入了CTE(Common Table Expression)以强化T-SQL。这是一个类似于非持久视图的好东东。阅读全文
posted @ 2009-10-23 01:35 邀月 阅读(4309) | 评论 (15) 编辑
原文地址:https://www.cnblogs.com/Leo_wl/p/2434668.html