理解 CUBE 和 ROLLUP 之间的区别

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

我有点困惑,向我的教授求助。她给我发了一封电子邮件,询问我如何回答这个问题: “每种类型和版本的炉子有多少个? 对于一个挑战,但没有额外的积分,包括总数的炉子。“

这是她发给我的问题:

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 子句,并从 微软的一篇文章开始。它说,ROLLUP 条款类似于 CUBE 条款,但它与 CUBE 条款有以下区别:

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

因此,我决定用 CUBE 替换查询中的 ROLLUP,看看会发生什么。他们产生了相同的结果。我想这就是我困惑的地方。

看起来,如果您使用的是我在这里提到的查询类型,那么这两个子句之间似乎没有任何实际区别。是吗?或者,我是不是听不懂你在说什么?当我读完微软的那篇文章时,我曾经想过,使用 CUBE 子句时,我的结果应该是不同的。

96573 次浏览

您不会看到任何区别,因为您只是卷起一列

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

这就是为什么你没有看到区别,因为你只有一个专栏,你卷起来。

希望能帮上忙。

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

添加 Group by InvoiceDt, InvoiceCountry(或任何字段将给你更多的数据。

使用 Cube 将为每个 InvoiceDt 给出一个 Sum,并且您将为每个 InvoiceCountry 获得一个 Sum。

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

您可以找到更多关于分组设置、立方体、滚动的详细信息。它们只是以某种方式展开 GROUP BY + UNION ALL 以获得聚合:)

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

所有投票结果都是正确的。


一个重要的区别是

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

进一步阅读请参阅我关于火花 sql 的文章

例如:

Store _ id,product _ type

Rollup 等效于

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个列组合