了解CUBE和ROLLUP之间的差异

kre*_*ack 64 sql t-sql sql-server sql-server-2008

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

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

这是她发给我的查询:

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

所以,我调整了那个查询,直到满足了我的需求.这就是我想出的:

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

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

无论如何,我决定阅读ROLLUP条款,并从微软的一篇文章开始.它说ROLLUP子句类似于CUBE子句,但是它通过以下方式区别于CUBE子句:

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

所以,我决定用CUBE替换我的查询中的ROLLUP,看看会发生什么.他们产生了相同的结果.我猜这就是我感到困惑的地方.

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

Der*_*omm 151

您不会看到任何差异,因为您只是卷起一列.考虑一下我们的例子

ROLLUP (YEAR, MONTH, DAY)

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

YEAR, MONTH, DAY
YEAR, MONTH
YEAR
()
Run Code Online (Sandbox Code Playgroud)

有了CUBE,它将具有以下内容:

YEAR, MONTH, DAY
YEAR, MONTH
YEAR, DAY
YEAR
MONTH, DAY
MONTH
DAY
()
Run Code Online (Sandbox Code Playgroud)

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

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

希望有所帮助.

  • 有趣.我想知道为什么设计师不只是选择一个并为它的行为添加一个额外的属性参数.对于那些基本相同但略有不同的东西有两个不同的名称是非常愚蠢的. (2认同)

Sar*_*avu 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
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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
Run Code Online (Sandbox Code Playgroud)

以下是(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
Run Code Online (Sandbox Code Playgroud)

以下是(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
Run Code Online (Sandbox Code Playgroud)

以下是结果 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
Run Code Online (Sandbox Code Playgroud)

现在您将获得以下结果

在此输入图像描述


Jef*_*ffO 6

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

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

使用Cube将为每个InvoiceDt提供一个Sum,您将获得每个InvoiceCountry的Sum.