1.创建表 Staff

CREATE TABLE [dbo].[Staff](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](50) NULL,
[Sex] [varchar](50) NULL,
[Department] [varchar](50) NULL,
[Money] [int] NULL,
[CreateDate] [datetime] NULL
) ON [PRIMARY] GO

2.为Staff表填充数据

INSERT INTO [dbo].[Staff]([Name],[Sex],[Department],[Money],[CreateDate])
SELECT 'Name1','男','技术部',3000,'2011-11-12'
UNION ALL
SELECT 'Name2','男','工程部',4000,'2013-11-12'
UNION ALL
SELECT 'Name3','女','工程部',3000,'2013-11-12'
UNION ALL
SELECT 'Name4','女','技术部',5000,'2012-11-12'
UNION ALL
SELECT 'Name5','女','技术部',6000,'2011-11-12'
UNION ALL
SELECT 'Name6','女','技术部',4000,'2013-11-12'
UNION ALL
SELECT 'Name7','女','技术部',5000,'2012-11-12'
UNION ALL
SELECT 'Name8','男','工程部',3000,'2012-11-12'
UNION ALL
SELECT 'Name9','男','工程部',6000,'2011-11-12'
UNION ALL
SELECT 'Name10','男','工程部',3000,'2011-11-12'
UNION ALL
SELECT 'Name11','男','技术部',3000,'2011-11-12'

GROUP BY 分组查询, 一般和聚合函数配合使用

SELECT  [DEPARTMENT],SEX, COUNT(1)
FROM DBO.[STAFF]
GROUP BY SEX, [DEPARTMENT]

该段SQL是用于查询   某个部门下的男女员工数量 其数据结果如下

开销比较大

GROUPING SETS

使用 GROUPING SETS 的 GROUP BY 子句可以生成一个等效于由多个简单 GROUP BY 子句的 UNION ALL 生成的结果集,并且其效率比 GROUP BY 要高,SQL Server 2008引入。

1.使用GROUP BY 子句的 UNION ALL 来统计 Staff 表中的性别、部门、薪资、入职年份

SET STATISTICS IO ON
SET STATISTICS TIME ON SELECT N'总人数' ,'',COUNT(0) FROM [DBO].[STAFF]
UNION ALL
SELECT N'按性别划分', SEX,COUNT(0) FROM [DBO].[STAFF] GROUP BY SEX
UNION ALL
SELECT N'按部门统计',[DEPARTMENT],COUNT(0) FROM [DBO].[STAFF] GROUP BY [DEPARTMENT]
UNION ALL
SELECT N'按薪资统计',CONVERT(VARCHAR(10),[MONEY]),COUNT(0) FROM [DBO].[STAFF] GROUP BY [MONEY]
UNION ALL
SELECT N'按入职年份',CONVERT(VARCHAR(10),YEAR([CREATEDATE])),COUNT(0) FROM [DBO].[STAFF] GROUP BY YEAR([CREATEDATE])


2.换成GROUPING SETS的写法

SET STATISTICS IO ON
SET STATISTICS TIME ON
GO
SELECT (CASE
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=15 THEN N'总人数'
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=7 THEN N'按性别划分'
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=11 THEN N'按部门统计'
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=13 THEN N'按薪资统计'
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=14 THEN N'按入职年份'
END
),
(CASE
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=15 THEN ''
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=7 THEN SEX
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=11 THEN [DEPARTMENT]
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=13 THEN CONVERT(VARCHAR(10),[MONEY])
WHEN GROUPING_ID(SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]))=14 THEN CONVERT(VARCHAR(10),YEAR([CREATEDATE]))
END
)
,
COUNT(1)
FROM DBO.[STAFF]
GROUP BY GROUPING SETS (SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]),())

从上述结果中可以看出,采用UNION ALL 是多次扫描表,并将扫描后的查询结果进行组合操作,会增加IO开销,减少CPU和内存开销。

采用GROUPING SETS 是一次性读取所有数据,并在内存中进行聚合操作生成结果,减少IO开销,对CPU和内存消耗增加。但GROUPING SETS 在多列分组时,其性能会比group by高。

这里扫描四次是因为我 GROUP BY GROUPING SETS (SEX,[DEPARTMENT],[MONEY],YEAR([CREATEDATE]),()) 了四列

ROLLUP与CUBE 

ROLLUP与CUBE  按一定的规则产生多种分组,然后按各种分组统计数据

ROLLUP与CUBE 区别:

  CUBE 会对所有的分组字段进行统计,然后合计。

  ROLLUP 按照分组顺序,对第一个字段进行组内统计,最后给出合计。
 
下面看我查询 
SELECT
CASE WHEN (GROUPING(SEX) = 1) THEN '统计-ROLLUP'
ELSE ISNULL(SEX, 'UNKNOWN')
END AS SEX ,
COUNT(0)
FROM DBO.[STAFF]
GROUP BY SEX WITH ROLLUP SELECT
CASE WHEN (GROUPING(SEX) = 1) THEN '统计-CUBE'
ELSE ISNULL(SEX, 'UNKNOWN')
END AS SEX ,
COUNT(0)
FROM DBO.[STAFF]
GROUP BY SEX WITH CUBE

看不出差别,我们再加一列
SELECT
CASE WHEN (GROUPING(SEX) = 1) THEN '统计-ROLLUP'
ELSE ISNULL(SEX, 'UNKNOWN')
END AS SEX ,
CASE WHEN (GROUPING([DEPARTMENT]) = 1) THEN '统计-ROLLUP'
ELSE ISNULL([DEPARTMENT], 'UNKNOWN')
END AS [DEPARTMENT],
COUNT(0)
FROM DBO.[STAFF]
GROUP BY SEX,[DEPARTMENT] WITH ROLLUP SELECT
CASE WHEN (GROUPING(SEX) = 1) THEN '统计-CUBE'
ELSE ISNULL(SEX, 'UNKNOWN')
END AS SEX ,
CASE WHEN (GROUPING([DEPARTMENT]) = 1) THEN '统计-CUBE'
ELSE ISNULL([DEPARTMENT], 'UNKNOWN')
END AS [DEPARTMENT],
COUNT(0)
FROM DBO.[STAFF]
GROUP BY SEX,[DEPARTMENT] WITH CUBE

可以看出 使用 ROLLUP 会先统计分组下的,然后在对GROUP BY的第一列字段进行统计,最后计算总数,而 CUBE 则是先分组统计,然后统计GRUOP BY 的每个字段,最后进行汇总。

http://www.cnblogs.com/woxpp/p/4688715.html

SQL Server 之 GROUP BY、GROUPING SETS、ROLLUP、CUBE的更多相关文章

  1. SQL GROUP BY GROUPING SETS,ROLLUP,CUBE(需求举例)

    实现按照不同级别分组统计 关于GROUP BY 中的GROUPING SETS,ROLLUP,CUBE 从需求的角度理解会更加容易些. 需求举例: 假如一所学校只有两个系, 每个系有两个专业, 每个专 ...

  2. Oracle PL/SQL之GROUP BY GROUPING SETS

    [转自] http://blog.csdn.net/t0nsha/article/details/6538838 使用GROUP BY GROUPING SETS相当于把需要GROUP的集合用UNIO ...

  3. GROUPING SETS、CUBE、ROLLUP

    其实还是写一个Demo 比较好 USE tempdb IF OBJECT_ID( 'dbo.T1' , 'U' )IS NOT NULL BEGIN DROP TABLE dbo.T1; END; G ...

  4. group by <grouping sets(...) ><cube(...)>

    GROUP BY      GROUPING SETS() 后面将还会写学习 with cube,  with rollup,以及将它们转换为标准的GROUP BY的子句GROUP SET(), CU ...

  5. SQL server 关于 GROUP BY 详细讲解和用法

    1. Group By 语句简介: Group By语句从英文的字面意义上理解就是“根据(by)一定的规则进行分组(Group)”.它的作用是通过一定的规则将一个数据集划分成若干个小的区域,然后针对若 ...

  6. Group By Grouping Sets

    Group by分组函数的自定义,与group by配合使用可更加灵活的对结果集进行分组,Grouping sets会对各个层级进行汇总,然后将各个层级的汇总值union all在一起,但却比单纯的g ...

  7. GROUP BY GROUPING SETS 示例

    --建表 create table TEst1 ( ID ), co_CODE ), T_NAME ), Money INTEGER, P_code ) ); --插入基础数据 insert into ...

  8. Hive高级聚合GROUPING SETS,ROLLUP以及CUBE

    scala> import org.apache.spark.sql.hive.HiveContextimport org.apache.spark.sql.hive.HiveContext s ...

  9. (4.6)sql2008中的group by grouping sets

    最近遇到一个情况,需要在内网系统中出一个统计报表.需要根据不同条件使用多个group by语句.需要将所有聚合的数据进行UNION操作来完成不同维度的统计查看. 直到发现在SQL SERVER 200 ...

随机推荐

  1. java1.7集合源码阅读: Vector

    Vector是List接口的另一实现,有非常长的历史了,从jdk1.0开始就有Vector了,先于ArrayList出现,与ArrayList的最大区别是:Vector 是线程安全的,简单浏览一下Ve ...

  2. centos添加开机启动项目

    centOS 配置开机自启动两种方式: 1.vi /etc/rc.d/rc.local 在此文件中加入启动的脚本 2.chkconfig 增加自己的脚本  --add --list --del 步骤: ...

  3. 02-JAVA中的基本语法

    第一个动手动脑: 首先用枚举类型定义两个变量,然后判断两个变量是否引用同一对象,在判断枚举类型是否是原始数据类型,再从字符串中转换,最后列出所有的对象. 很明显,这两个变量都是枚举类型,但是这两个变量 ...

  4. ubuntu14.04 的网络配置

    为eth0 配置网络 vi /etc/network/intefaces 添加以下内容 auto eth0 iface eth0 inet static address 192.168.0.10 ne ...

  5. PoEdu - C++阶段班- Lesson02_C to C++

    1  原生bool类型 c++里面的bool类型才是真正原生的true和faul,比如常见的大写的"BOOL",它就不是原生的. 原生的与非原生的bool,它们的区别: 详细说下原 ...

  6. iOS 微信支付

    相关资料 SDK下载:https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=11_1 APP端开发步骤说明:https://pay.weixin ...

  7. win2008server系统下文件替换权限

    因为那里的文件默认只有系统才有修改权限.选中要替换的文件(一次只能选一个),属性->安全->高级->所有者(选更改)->高级->立即查找->选择 Everyone, ...

  8. Oracle中用一条Sql实现任意的行转列拼接 多行拼接

    表结构和数据如下(表名Test): NO VALUE NAME 1 a 测试1 1 b 测试2 1 c 测试3 1 d 测试4 2 e 测试5 4 f 测试6 4 g 测试7 Sql语句: selec ...

  9. 去除html标签 正则表达式

    /// <summary>        /// 去除html标签        /// </summary>        public static string Clea ...

  10. PAT

    PAT将每个全局IP地址的可用端口号分为3个部分0~511,512~1023,1023~65535.当PAT从地址池中获取地址时,首先维持源端口不变.如果不可能,它再从池中起始部分搜索可用的端口,如果 ...