了解CUBE和ROLLUP之间的差异

时间:2011-08-13 21:41:37

标签: sql sql-server sql-server-2008 tsql

我的任务要求我找出“为每个日期写了多少发票?”

我有点陷入困境,并向我的教授寻求帮助。她通过电子邮件向我发送了一个查询,回答了这个问题:“每种类型和版本的炉子有多少? 对于挑战但没有额外的积分,包括炉灶的总数。“

这是她发给我的查询:

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. CUBE生成一个结果集,显示所选列中所有值组合的聚合。
  2. ROLLUP生成一个结果集,显示所选列中值的层次结构的聚合。
  3. 所以,我决定用CUBE替换查询中的ROLLUP,看看会发生什么。他们产生了相同的结果。我猜这就是我感到困惑的地方。

    看起来,如果您使用的是我在这里的查询类型,那么这两个条款之间没有任何实际区别。是对的吗?或者,我不明白什么?当我读完微软文章时,我曾想过,使用CUBE子句我的结果应该是不同的。

5 个答案:

答案 0 :(得分:144)

由于您只是汇总了一个列,因此您不会看到任何差异。考虑我们做的一个例子

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将)

这就是为什么你没有看到差异,因为你只有一个列卷起来。

希望有所帮助。

答案 1 :(得分:74)

我们可以通过一个简单的例子来理解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

enter image description here

<强> 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)

的结果

enter image description here

(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)

的结果

enter image description here

<强> 2。 CUBE (一次性查找季度以及学生的总数)

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

的结果

enter image description here

现在您可能想知道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

现在您将获得以下结果

enter image description here

答案 2 :(得分:6)

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

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

使用Cube将为每个InvoiceDt提供一笔总和,您将获得每个InvoiceCountry的总和。

答案 3 :(得分:1)

你可以找到更多关于GROUPING SET,CUBE,ROLL UP的信息。 TL; DR他们只是在某些方面扩展GROUP BY + UNION ALL以获得聚合:)

https://technet.microsoft.com/en-us/library/bb510427(v=sql.105).aspx

答案 4 :(得分:0)

所有投票的答案都很好。


一个重要的区别是

  1. ROLLUP 规范的 N 个元素对应于 N+1 GROUPING 设置。
  2. CUBE 规范的 N 个元素对应于 2^N GROUPING 设置。

Further reading see my article with respect to spark sql

例如:

store_id,product_type

rollup 等价于

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

for 2 (n) group by columns grouping set has (n+1) = 3 个组合列

立方体相当于

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

for 2 (n) group by columns 分组集有 (2^n ) = 4 个列组合