ROLLUP 与 CUBE 运算符的使用

    对于数据的汇总,是数据库经常用到的任务之一,除了我们通常使用的GROUP BY分组配合聚合函数对数据汇总,以及使用UNION ALL 对数据汇总之外,SQL还提供了 GROUP BY Col1,Col2.. WITH CUBE | ROLLUP,以及COMPUTE BY 等汇总方式,本文主要介绍了使用CUBE 与ROLLUP运算符来实现数据的分级汇总。

IF OBJECT_ID('tb') IS NOT NULL
 DROP TABLE tb;
GO  
CREATE TABLE tb
(
    Provider    VARCHAR(10)
    ,MaterialNo VARCHAR(3)
    ,Quantity INT
   
); 
INSERT INTO tb SELECT 'Canon',  '001',  500 
UNION ALL SELECT 'Canon',  '001',     200 
UNION ALL SELECT 'Canon',  '002',     100
UNION ALL SELECT 'Canon',  '002',     300
UNION ALL SELECT 'Sony',  '001',     200 
UNION ALL SELECT 'IBM',  '002',     100 
UNION ALL SELECT 'IBM',  '001',     600 
UNION ALL SELECT 'IBM',  '001',     200  

 

--1.使用ROLLUP来对数据进行汇总
SELECT Provider,MaterialNo,SUM(Quantity) AS Sum_Quantity FROM tb
GROUP BY Provider,MaterialNo
WITH ROLLUP
/*  --结果
Provider   MaterialNo Sum_Quantity
---------- ---------- ------------
Canon      001        700
Canon      002        400
Canon      NULL       1100
IBM        001        800
IBM        002        100
IBM        NULL       900
Sony       001        200
Sony       NULL       200
NULL       NULL       2200
*/
由结果可以得知,ROLLUP运算符实现了对Provider级别进行汇总,结果集中Provider字段不为空,MaterialNo字段为空的时候实现了对不同的Provider分类汇总,而当Provider与MaterialNo都为空时则是对所有的Provider来实现数据汇总。

 

--2.使用CUBE来对数据进行汇总
SELECT Provider,MaterialNo,SUM(Quantity) AS Sum_Quantity FROM tb
GROUP BY Provider,MaterialNo
WITH CUBE
/*  --结果
Provider   MaterialNo Sum_Quantity
---------- ---------- ------------
Canon      001        700
Canon      002        400
Canon      NULL       1100
IBM        001        800
IBM        002        100
IBM        NULL       900
Sony       001        200
Sony       NULL       200
NULL       NULL       2200
NULL       001        1700
NULL       002        500
*/
与ROLLUP相比,从结果可以看出CUBE的结果集在ROLLUP结果集的基础上增加了两行,
NULL       001        1700
NULL       002        200
即对不同MaterialNo也实现了汇总。

 

--3.ROLLUP与CUBE的差异
 . ROLLUP 生成的结果集为所选列中值的某一维度的聚合。如以上示例中实现了对Provider维度进行汇总。
 . CUBE  生成的结果集为所选列中值的所有维度的聚合。如以上示例中实现了对Provider和MaterialNo所有维度进行汇总。
 
--4.使用GROUPING函数来处理汇总产生的NULL值
     对于使用ROLLUP与CUBE汇总数据所产生的NULL值,容易引起与实际数据本身为NULL容易引起歧义,对此我们可以使用GROUPING函数的进行区分。
     当NULL为ROLLUP或CUBE所产生时,则GROUPING函数返回的值为1,当NULL来自实际数据本身的话,GROUPING函数返回的值为0。
SELECT
    CASE WHEN (GROUPING(Provider) = 1) THEN 'ALL'
         ELSE Provider END AS Provider,
    CASE WHEN (GROUPING(MaterialNo) = 1) THEN 'ALL'
         ELSE MaterialNo END AS MaterialNo,
    SUM(Quantity) AS Sum_Quantity FROM tb
GROUP BY Provider,MaterialNo
WITH CUBE 
/*  --结果
Provider   MaterialNo Sum_Quantity
---------- ---------- ------------
Canon      001        700
Canon      002        400
Canon      ALL        1100
IBM        001        800
IBM        002        100
IBM        ALL        900
Sony       001        200
Sony       ALL        200
ALL        ALL        2200
ALL        001        1700
ALL        002        500
*/

 

--5.使用Having子句来顾虑掉无用的数据,比如本例过滤掉了总计以及MaterialNo汇总的数据。
SELECT
    CASE WHEN (GROUPING(Provider) = 1) THEN 'ALL'
         ELSE Provider END AS Provider,
    CASE WHEN (GROUPING(MaterialNo) = 1) THEN 'ALL'
         ELSE MaterialNo END AS MaterialNo,
    SUM(Quantity) AS Sum_Quantity FROM tb
GROUP BY Provider,MaterialNo WITH CUBE
HAVING GROUPING(Provider) <> 1
/*  --结果
Provider   MaterialNo Sum_Quantity
---------- ---------- ------------
Canon      001        700
Canon      002        400
Canon      ALL        1100
IBM        001        800
IBM        002        100
IBM        ALL        900
Sony       001        200
Sony       ALL        200
*/

 

--过滤掉了相同Provider,不同的MaterialNo 的小计数据和最终的总计数据
SELECT
    CASE WHEN (GROUPING(Provider) = 1) THEN 'ALL'
         ELSE Provider END AS Provider,
    CASE WHEN (GROUPING(MaterialNo) = 1) THEN 'ALL'
         ELSE MaterialNo END AS MaterialNo,
    SUM(Quantity) AS Sum_Quantity FROM tb
GROUP BY Provider,MaterialNo WITH CUBE
HAVING GROUPING(MaterialNo) = 0

 

总结:CUBE,ROLLUP为多维数据集的汇总提供了可能,当需要对所有维度进行汇总,应当使用CUBE运算符,对某一维度进行汇总则使用ROLLUP运算法。
     需要注意的是,WITH CUBE | ROLLUP必须跟在GROUP BY Col1,Col2列之后,然后可以通过使用HAVING子句配合GROUPING函数来过滤不需要的结果集。

时间: 2024-12-17 19:42:07

ROLLUP 与 CUBE 运算符的使用的相关文章

SQLServer中汇总功能的使用GROUPING,ROLLUP和CUBE

第一次看到这样的SQL语句,看不懂,其中用到了下面的不常用的 聚集函数:GROUPING 用于汇总数据用的运算符: ROLLUP SELECT CASE GROUPING(o.customerid) WHEN 0 THEN o.customerid ELSE  '(Total)' END AS AllCustomersSummary, CASE GROUPING(od.orderid) WHEN 0 THEN od.orderid ELSE -1 END AS IndividualCustome

SQL Server 之 GROUP BY、GROUPING SETS、ROLLUP、CUBE

原文:SQL Server 之 GROUP BY.GROUPING SETS.ROLLUP.CUBE 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] [date

SQL基础--&amp;gt; 约束(CONSTRAINT)

--============================= --SQL基础--> 约束(CONSTRAINT) --=============================   一.几类数据完整性     实体完整性:表中记录不重复(任何两条记录不全等)并且每条记录都有一个非空主键     域完整性:表中字段值必须与字段数据类型.格式.有效范围相吻合     参照完整性:不能引用不存在的值     自定义完整性:根据特定业务领域定义的需求完整性         保证数据完整性的几种常用方法

收缩表段(shrink space)

--====================-- 收缩表段(shrink space)--==================== 一.表的增长方式    当表被创建后,随着记录的不断插入,组成表的区间会被填满,如果启用了自动扩展,则当区间填满后,会分配新的区间.假定高水    位线随着记录的增加从最左端往右端来移动,当到底部区间的尾端时,则新的区间将会被分配.    二.表可收缩的原理    随着记录的增加高水位线不断的右移,记录的删除不会导致高水位线往回(左)移动    删除记录后的空闲空间

PL/SQL --&amp;gt; DML 触发器

--======================= -- PL/SQL --> DML 触发器 --=======================         何谓触发器?简言之,是一段命名的PL/SQL代码块,只不过该代码块在特定的条件下被触发并且执行.对于这样的代码我们称之为触发器 .触发器根据触发类型的不同又分为不同级别的触发器,下面将给出触发器的分类,定义,以及使用的示例.   一.触发器的相关概念     1.触发器的分类         通常根据触发条件以及触发级别的不同分为DM

PL/SQL --&amp;gt; INSTEAD OF 触发器

--============================== -- PL/SQL --> INSTEAD OF 触发器 --==============================       INSTEAD OF 触发器常用于管理编写不可更新的视图,INSTEAD-OF触发器必须是行级的.     可以用INSTEAD OF触发器来解释INSERT.UPDATE和DELETE语句,并用备用的程序代码替换那些指令.   一.不可更新视图     基于下列情形创建的视图,不可直接对其进行D

PL/SQL --&amp;gt; 函数

--================== -- PL/SQL --> 函数 --==================       函数通常用于返回特定的数据.其实质是一个有名字的PL/SQL块,作为一个schema对象存储于数据库,可以被反复执行.函数通常被作为 一个表达式来调用或存储过程的一个参数,具有返回值.   一.建立函数的语法     CREATE [ OR REPLACE ] FUNCTION function_name         (argument1 [mode1] data

db_block_checking与db_block_checksum

--************************************ -- db_block_checking 与 db_block_checksum --************************************     db_block_checking与db_block_checksum两个参数都是对block进行检查,然而两者很容易混淆.事实上,两个参数中前者是对块做逻 辑性检查,后者则是做物理性检查.两者各司其职,并不矛盾.下面分别给出具体描述. 1.db_blo

Oracle 常用性能视图一览表(10g)

--*************************************-- Oracle 常用性能视图一览表(10g)--************************************* Advisors     Information related to cache advisors v$pga_target_advice v$shared_pool_advice v$pga_target_advice_histogram v$java_pool_advice v$mttr