CUBE 和 ROLLUP 之间的具体区别

ROLLUP 运算符生成的结果集类似于 CUBE 运算符生成的结果集。

下面是 CUBE 和 ROLLUP 之间的具体区别:

  • CUBE 生成的结果集显示了所选列中值的所有组合的聚合。
  • ROLLUP 生成的结果集显示了所选列中值的某一层次结构的聚合。

ROLLUP 优点:

  •  
    • (1)ROLLUP 返回单个结果集,而 COMPUTE BY 返回多个结果集,而多个结果集会增加应用程序代码的复杂性。
    • (2)ROLLUP 可以在服务器游标中使用,而 COMPUTE BY 则不可以。
    • (3)有时,查询优化器为 ROLLUP 生成的执行计划比为 COMPUTE BY 生成的更为高效。
    •  

下面对比一下GROUP BY 、CUBE 和  ROLLUP后的结果

创建表:

CREATE TABLE DEPART
(部门 char(10),员工 char(6),工资 int)

INSERT INTO DEPART SELECT 'A','ZHANG',100
INSERT INTO DEPART SELECT 'A','LI',200
INSERT INTO DEPART SELECT 'A','WANG',300
INSERT INTO DEPART SELECT 'A','ZHAO',400
INSERT INTO DEPART SELECT 'A','DUAN',500
INSERT INTO DEPART SELECT 'B','DUAN',600
INSERT INTO DEPART SELECT 'B','DUAN',700

部门         员工         工资

A             ZHANG     100
A             LI             200
A             WANG      300
A             ZHAO      400
A             DUAN      500
B             DUAN      600
B             DUAN      700

 

(1)GROUP BY 

SELECT 部门,员工,SUM(工资)AS TOTAL
from DEPART
GROUP BY 部门,员工

结果:

A             DUAN      500
B             DUAN      1300
A             LI        200
A             WANG      300
A             ZHANG     100
A             ZHAO      400

(2)ROLLUP

SELECT 部门,员工,SUM(工资)AS TOTAL
from DEPART
GROUP BY  部门,员工  WITH ROLLUP

结果如下:

A             DUAN       500
A             LI             200
A             WANG      300
A             ZHANG     100
A             ZHAO       400
A             NULL        1500
B             DUAN       1300
B             NULL       1300
NULL       NULL        2800

ROLLUP结果集中多了三条汇总信息:即部门A的合计,部门B的合计以及总合计。其中将部门B中的DUAN合计。

等价于下列SQL语句

SELECT 部门,员工,SUM(工资)AS TOTAL
from DEPART
GROUP BY 部门,员工
union
SELECT 部门,'NULL',SUM(工资)AS TOTAL
from DEPART
GROUP BY  部门
union
SELECT 'NULL','NULL',SUM(工资)AS TOTAL
from DEPART

结果:

A             DUAN      500
A             LI           200
A             NULL      1500
A             WANG      300
A             ZHANG     100
A             ZHAO       400
B             DUAN      1300
B             NULL       1300
NULL       NULL        2800

(3)CUBE

SELECT 部门,员工,SUM(工资)AS TOTAL
from DEPART
GROUP BY 部门,员工 WITH CUBE

结果:

A             DUAN      500
A             LI           200
A             WANG      300
A             ZHANG     100
A             ZHAO      400
A             NULL      1500
B             DUAN      1300
B             NULL      1300
NULL    NULL         2800
NULL    DUAN        1800
NULL    LI               200
NULL    WANG       300
NULL    ZHANG       100
NULL    ZHAO         400

CUBE的结果集是在 ROLLUP结果集的基础上多了5行,这5行相当于在ROLLUP结果集上在union 上以员工 (即CUBE)为 GROUP BY的结果。

SELECT 部门,员工,SUM(工资)AS TOTAL
from DEPART
GROUP BY 部门,员工 WITH CUBE

等价于下列的SQL语句:

SELECT 部门,员工,SUM(工资)AS TOTAL
from DEPART
GROUP BY  部门,员工  WITH ROLLUP

union

SELECT 'NULL',员工,SUM(工资)AS TOTAL
from DEPART
GROUP BY 员工

结果:

NULL    NULL    2800
A             NULL    1500
A             DUAN      500
A             LI        200
A             WANG      300
A             ZHANG     100
A             ZHAO      400
B             NULL    1300
B             DUAN      1300
NULL    DUAN      1800
NULL    LI             200
NULL    WANG      300
NULL    ZHANG     100
NULL    ZHAO      400

 

****************************************************************

rollup 举例

****************************************************************

这里介绍sql server2005里面的一个使用实例:

CREATE TABLE tb(province nvarchar(10),city nvarchar(10),score int)

INSERT tb SELECT '陕西','西安',3

UNION ALL SELECT '陕西','安康',4

UNION ALL SELECT '陕西','汉中',2

UNION ALL SELECT '广东','广州',5

UNION ALL SELECT '广东','珠海',2

UNION ALL SELECT '广东','东莞',3

UNION ALL SELECT '江苏','南京',6

UNION ALL SELECT '江苏','苏州',1

GO

1、 只有一个汇总

select province as 省,sum(score) as 分数 from tb group by province with rollup

结果:

广东 10

江苏 7

陕西 9

NULL 26

select case when grouping(province)=1 then '合计' else province end as 省,sum(score) as 分数 from tb group by province with rollup

结果:

广东 10

江苏 7

陕西 9

合计 26

2、两级,中间小计最后汇总

select province as 省,city as 市,sum(score) as 分数 from tb group by province,city with rollup

结果:

广东 东莞 3

广东 广州 5

广东 珠海 2

广东 NULL 10

江苏 南京 6

江苏 苏州 1

江苏 NULL 7

陕西 安康 4

陕西 汉中 2

陕西 西安 3

陕西 NULL 9

NULL NULL 26

select province as 省,city as 市,sum(score) as 分数,grouping(province) as g_p,grouping(city) as g_c from tb group by province,city with rollup

结果:

广东 东莞 3 0 0

广东 广州 5 0 0

广东 珠海 2 0 0

广东 NULL 10 0 1

江苏 南京 6 0 0

江苏 苏州 1 0 0

江苏 NULL 7 0 1

陕西 安康 4 0 0

陕西 汉中 2 0 0

陕西 西安 3 0 0

陕西 NULL 9 0 1

NULL NULL 26 1 1

select case when grouping(province)=1 then '合计' else province end 省,

case when grouping(city)=1 and grouping(province)=0 then '小计' else city end 市,

sum(score) as 分数

from tb group by province,city with rollup

结果:

广东 东莞 3

广东 广州 5

广东 珠海 2

广东 小计 10

江苏 南京 6

江苏 苏州 1

江苏 小计 7

陕西 安康 4

陕西 汉中 2

陕西 西安 3

陕西 小计 9

合计 NULL 26

 

****************************************************************

cube举例

****************************************************************

使用cube操作符时,最多可以有10个分组表达式

在cube中不能使用all关键字

举例

例如,简单表 Inventory 包含下列数据:

Item                 Color                Quantity                  

-------------------- -------------------- --------------------------

Table                Blue                 124                       

Table                Red                  223                       

Chair                Blue                 101                        

Chair                Red                  210                       

以下查询将返回一个结果集,其中包含 DE>ItemDE> 和 DE>ColorDE> 的所有可能组合的 DE>QuantityDE> 小计:

SELECT Item, Color, SUM(Quantity) AS QtySum

FROM Inventory

GROUP BY Item, Color WITH CUBE

下面是结果集:

Item                 Color                QtySum                    

-------------------- -------------------- --------------------------

Chair                Blue                 101.00                    

Chair                Red                  210.00                    

Chair                (null)               311.00                    

Table                Blue                 124.00                    

Table                Red                  223.00                    

Table                (null)               347.00                    

(null)               (null)               658.00                    

(null)               Blue                 225.00                    

(null)               Red                  433.00                    

我们着重考查结果集中的以下几行:

Chair                (null)               311.00                    

此行报告了在 DE>ItemDE> 维度中包含 DE>ChairDE> 值的所有行的小计。对 DE>ColorDE> 维度返回了 DE>nullDE> 值,用以表示该行报告的聚合包括 DE>ColorDE> 维度为任意值的行。

Table                (null)               347.00                    

这一行类似,但报告的是 DE>ItemDE> 维度中包含 DE>TableDE> 值的所有行的小计。

(null)               (null)               658.00                    

这一行报告了多维数据集的总计。DE>ItemDE> 和 DE>ColorDE> 维度都包含 DE>nullDE> 值。这表示此行中汇总了这两个维度的所有值。

(null)               Blue                 225.00                    

(null)               Red                  433.00                    

这两行报告了 DE>ColorDE> 维度的小计。两行中的 DE>ItemDE> 维度值都是 DE>nullDE>,表示聚合数据来自 DE>ItemDE> 维度为任意值的行。

  使用 GROUPING 区分空值

CUBE 操作生成空值将会带来一个问题:如何区分 CUBE 操作生成的 NULL 值和在实际数据中返回的 NULL 值?可以使用 GROUPING 函数解决此问题。如果列值来自事实数据,GROUPING 函数将返回 0;如果列值是由 CUBE 操作生成的 NULL,则返回 1。在 CUBE 操作中,生成的 NULL 代表所有值。可以编写 SELECT 语句以使用 GROUPING 函数将生成的任一 NULL 替换为字符串 ALL。由于事实数据中的 NULL 表示数据值未知,因此也可以将 SELECT 编码为返回字符串 UNKNOWN,用于表示事实数据中的 NULL。例如:

SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL'

            ELSE ISNULL(Item, 'UNKNOWN')

       END AS Item,

       CASE WHEN (GROUPING(Color) = 1) THEN 'ALL'

            ELSE ISNULL(Color, 'UNKNOWN')

       END AS Color,

       SUM(Quantity) AS QtySum

FROM Inventory

GROUP BY Item, Color WITH CUBE

  多维数据集

CUBE 运算符可用于生成 n 维的多维数据集,即具有任意维数的多维数据集。只有一个维度的多维数据集可用于生成合计,例如:

SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL'

            ELSE ISNULL(Item, 'UNKNOWN')

       END AS Item,

       SUM(Quantity) AS QtySum

FROM Inventory

GROUP BY Item WITH CUBE

GO

此 DE>SELECTDE> 语句返回的结果集既显示了 DE>ItemDE> 中每个值的小计,也显示了 DE>ItemDE> 中所有值的总计:

Item                 QtySum                    

-------------------- --------------------------

Chair                311.00                     

Table                347.00                    

ALL                  658.00                    

包含具有多个维度的 CUBE 的 SELECT 语句可生成大型结果集,因为这些语句会为所有维度中各值的所有组合都生成相应的行。这些大型结果集包含的数据可能会过多而不易于阅读和理解。此问题的一种解决办法是将 DE>SELECTDE> 语句放入视图中:

CREATE VIEW InvCube AS

SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL'

            ELSE ISNULL(Item, 'UNKNOWN')

       END AS Item,

       CASE WHEN (GROUPING(Color) = 1) THEN 'ALL'

            ELSE ISNULL(Color, 'UNKNOWN')

       END AS Color,

       SUM(Quantity) AS QtySum

FROM Inventory

GROUP BY Item, Color WITH CUBE

然后即可用该视图来仅查询您感兴趣的维度值:

SELECT *

FROM InvCube

WHERE Item = 'Chair'

  AND Color = 'ALL'

 

Item                 Color                QtySum                    

-------------------- -------------------- --------------------------

Chair                ALL                  311.00                    

 

(1 row(s) affected)

posted @ 2011-03-10 09:54  Alex Tian  阅读(7309)  评论(0编辑  收藏  举报