我的任务要求我找出“为每个日期写了多少发票?”
我有点陷入困境,并向我的教授寻求帮助。她通过电子邮件向我发送了一个查询,回答了这个问题:“每种类型和版本的炉子有多少? 对于挑战但没有额外的积分,包括炉灶的总数。“
这是她发给我的查询:
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子句:
所以,我决定用CUBE替换查询中的ROLLUP,看看会发生什么。他们产生了相同的结果。我猜这就是我感到困惑的地方。
看起来,如果您使用的是我在这里的查询类型,那么这两个条款之间没有任何实际区别。是对的吗?或者,我不明白什么?当我读完微软文章时,我曾想过,使用CUBE子句我的结果应该是不同的。
答案 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
<强> 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。 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
现在您可能想知道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
现在您将获得以下结果
答案 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)
所有投票的答案都很好。
一个重要的区别是
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 个列组合