了解CUBE和ROLLUP之间的区别


70

我的作业要求我找出“每个日期写了多少张发票?”

我有点被困住了,向我的教授寻求帮助。她通过电子邮件向我发送了一个查询,该查询将回答以下问题:“每种类型和版本的炉灶数量已制成?要挑战但不要加分,请包括炉灶总数”。

这是她向我发送的查询:

SELECT STOVE.Type + STOVE.Version AS 'Type+Version'
, COUNT(*) AS 'The Count'
FROM STOVE
GROUP BY STOVE.Type + STOVE.Version WITH ROLLUP;

因此,我调整了该查询,直到满足我的需求为止。这是我想出的:

SELECT InvoiceDt
, COUNT(InvoiceNbr) AS 'Number of Invoices' 
FROM INVOICE 
GROUP BY InvoiceDt WITH ROLLUP 
ORDER BY InvoiceDt ASC;

它返回了我想要的以下结果。

无论如何,我决定阅读ROLLUP子句,并从Microsoft的文章开始。它说ROLLUP子句类似于CUBE子句,但是它通过以下方式与CUBE子句区分开:

  1. 多维数据集生成结果集,该结果集显示所选列中所有值组合的汇总。
  2. ROLLUP生成一个结果集,该结果集显示所选列中值层次结构的聚合。

因此,我决定将查询中的ROLLUP替换为CUBE以查看会发生什么。他们产生了相同的结果。我想那是我感到困惑的地方。

看起来,如果您使用的是我在这里使用的查询类型,则这两个子句之间没有任何实际区别。是对的吗?还是我不了解某事?我曾经想过,当我阅读完Microsoft文章时,使用CUBE子句的结果应该有所不同。

Answers:


159

您不会看到任何区别,因为您只汇总了一个列。考虑一个我们做的例子

ROLLUP (YEAR, MONTH, DAY)

使用ROLLUP,它将具有以下输出:

YEAR, MONTH, DAY
YEAR, MONTH
YEAR
()

使用CUBE,它将具有以下内容:

YEAR, MONTH, DAY
YEAR, MONTH
YEAR, DAY
YEAR
MONTH, DAY
MONTH
DAY
()

CUBE本质上包含每个节点的所有可能的汇总方案,而ROLLUP将层次结构保持不变(因此它不会跳过MONTH并显示YEAR / DAY,而CUBE会显示)

这就是为什么您没有看到差异的原因,因为您只有一个要汇总的列。

希望能有所帮助。


3
有趣。我想知道为什么设计人员不只是选择一个并为其行为添加额外的属性参数。为功能基本相同但略有不同的东西使用不同的名称是很愚蠢的。
mBrice1024 '17

77

我们可以通过一个简单的示例来了解ROLLUP和CUBE之间的区别。考虑我们有一张表格,其中包含学生季度考试的结果。在某些情况下,我们需要查看与季度以及学生对应的总数。这是样本表

SELECT * INTO #TEMP
FROM
(
    SELECT 'Quarter 1' PERIOD,'Amar' NAME ,97 MARKS
    UNION ALL
    SELECT 'Quarter 1','Ram',88 
    UNION ALL
    SELECT 'Quarter 1','Simi',76 
    UNION ALL
    SELECT 'Quarter 2','Amar',94 
    UNION ALL
    SELECT 'Quarter 2','Ram',82 
    UNION ALL
    SELECT 'Quarter 2','Simi',71 
    UNION ALL
    SELECT 'Quarter 3' ,'Amar',95 
    UNION ALL
    SELECT 'Quarter 3','Ram',83 
    UNION ALL
    SELECT 'Quarter 3','Simi',77
    UNION ALL
    SELECT 'Quarter 4' ,'Amar',91 
    UNION ALL
    SELECT 'Quarter 4','Ram',84 
    UNION ALL
    SELECT 'Quarter 4','Simi',79
)TAB

在此处输入图片说明

1. ROLLUP(可以找到一列对应的总数)

(a)获得每个季度所有学生的总成绩。

SELECT * FROM #TEMP
UNION ALL
SELECT PERIOD,NAME,SUM(MARKS) TOTAL
FROM #TEMP
GROUP BY NAME,PERIOD 
WITH ROLLUP
HAVING PERIOD IS NULL AND NAME IS NOT NULL 
// Having is used inorder to emit a row that is the total of all totals of each student

以下是(a)的结果

在此处输入图片说明

(b)如果您需要获得每个季度的总分

SELECT * FROM #TEMP
UNION ALL
SELECT PERIOD,NAME,SUM(MARKS) TOTAL
FROM #TEMP
GROUP BY PERIOD,NAME 
WITH ROLLUP
HAVING PERIOD IS NOT NULL AND NAME IS NULL

以下是(b)的结果

在此处输入图片说明

2.多维数据集(一次性查找季度和学生的总数)

SELECT PERIOD,NAME,SUM(MARKS) TOTAL
FROM #TEMP
GROUP BY NAME,PERIOD 
WITH CUBE
HAVING PERIOD IS NOT NULL OR NAME IS NOT NULL

以下是的结果 CUBE

在此处输入图片说明

现在您可能想知道ROLLUP和CUBE的实时使用。有时我们需要一份报告,其中需要一次查看每个季度的总数和每个学生的总数。这是一个例子

我将略微更改上述CUBE查询,因为我们需要两个总数的总数。

SELECT CASE WHEN PERIOD IS NULL THEN 'TOTAL' ELSE PERIOD END PERIOD,
CASE WHEN NAME IS NULL THEN 'TOTAL' ELSE NAME END NAME,
SUM(MARKS) MARKS
INTO #TEMP2
FROM #TEMP
GROUP BY NAME,PERIOD 
WITH CUBE

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + PERIOD + ']', 
               '[' + PERIOD + ']')
               FROM    (SELECT DISTINCT PERIOD FROM #TEMP2) PV  
               ORDER BY PERIOD    


DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT * FROM 
             (
                 SELECT * FROM #TEMP2
             ) x
             PIVOT 
             (
                 SUM(MARKS)
                 FOR [PERIOD] IN (' + @cols + ')
            ) p;' 

EXEC SP_EXECUTESQL @query

现在您将获得以下结果

在此处输入图片说明


6

这是因为您只有一个要分组的列。

添加Group by InvoiceDt, InvoiceCountry(或任何字段将为您提供更多数据。

使用多维数据集将为您提供每个InvoiceDt的总和,并且您将获得每个InvoiceCountry的总和。



0

所有投票的答案都是好的。


总的来说,一个重要的区别是

  1. ROLLUP规范的N个元素对应于N + 1个分组集。
  2. 多维数据集规范的N个元素对应于2 ^ N个分组集。

进一步阅读请参阅我的关于Spark SQL的文章

例如 :

store_id,产品类型

汇总等效于

GROUP BY store_id,product_type
 GROUPING SETS (
(store_id,product_type)
,(product_type)
, ())

对于2(n)个按列分组的分组,具有(n + 1)= 3个列的组合

立方体相当于

GROUP BY store_id,product_type
 GROUPING SETS (
(store_id,product_type)
,(store_id)
,(product_type)
, ())

对于2(n)个按列分组分组集具有(2 ^ n)= 4个列组合

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.