10

我有一个简单的查询:

WITH data(val1, val2, val3) AS
     ( SELECT 'a' ,'a-details' ,'1' FROM DUAL
     UNION ALL
     SELECT 'b' ,'b-details' ,'2' FROM DUAL
     UNION ALL
     SELECT 'c' ,'c-details' ,'3' FROM DUAL
     )
SELECT NVL(val1,'Total Result'),
     val2,
     SUM(val3) tot
from data
group by rollup(val1, val2);

我得到如下输出:

VAL1                             VAL2                                    TOT
-------------------------------- -------------------------------- ----------
a                                a-details                                 1 
a                                                                          1 
b                                b-details                                 2 
b                                                                          2 
c                                c-details                                 3 
c                                                                          3 
Total Result                                                               6 

但我需要一个像这样的输出:

VAL1                             VAL2                                    TOT
-------------------------------- -------------------------------- ----------
a                                a-details                                 1 
b                                b-details                                 2 
c                                c-details                                 3 
Total Result                                                               6 

提前致谢。

4

2 回答 2

11

GROUPING_ID 表达式

您可以使用该GROUPING_ID表达式来过滤您需要的小计级别:

WITH data AS
     ( SELECT 'a' AS val1 ,'a-details' AS val2 , '1' AS val3 FROM DUAL
     UNION ALL
     SELECT 'b' ,'b-details' ,'2' FROM DUAL
     UNION ALL
     SELECT 'c' ,'c-details' ,'3' FROM DUAL
     )
SELECT NVL(val1,'Total Result'),
     val2,
     SUM(val3) tot
from data
group by ROLLUP(val1, val2)
HAVING GROUPING_ID(val1, val2) IN (0, 3);

输出:

NVL(VAL1,'TOTALRESULT') VAL2 TOT
------------ --------- ----------
a-详细信息 1
b b-详细信息 2
c c-详细信息 3
总成绩 6

GROUPING_ID返回 0 表示没有小计的行,1 表示第一级等等,我们可以看看它返回的值:

WITH data AS
     ( SELECT 'a' AS val1 ,'a-details' AS val2 , '1' AS val3 FROM DUAL
     UNION ALL
     SELECT 'b' ,'b-details' ,'2' FROM DUAL
     UNION ALL
     SELECT 'c' ,'c-details' ,'3' FROM DUAL
     )
SELECT NVL(val1,'Total Result'),
     val2,
     SUM(val3) tot,
     GROUPING_ID(val1, val2) AS grp_id
from data
group by ROLLUP(val1, val2);
NVL(VAL1,'TOTALRESULT') VAL2 TOT GRP_ID
------------ --------- ---------- -------- --
a a-详细信息 1 0
一个 1 1
b b-详细信息 2 0
乙 2 1
c c-详细信息 3 0
3 1
总结果 6 3

在 SQLFiddle 检查

有关 Rollup 和相关主题的更多信息:Tim Hall 关于 Rollup 和 Cube

编辑

分组功能

关于评论。您可以使用以下GROUPING功能:

GROUPING - 接受单个列作为参数,如果该列包含由 ROLLUPorCUBE操作作为小计的一部分生成的空值,则返回“1”,对于任何其他值(包括存储的空值),则返回“0”。

返回值示例:

WITH data AS
     ( SELECT 'a' AS val1 ,'a-details' AS val2 , '1' AS val3 FROM DUAL
     UNION ALL
     SELECT 'b' ,'b-details' ,'2' FROM DUAL
     UNION ALL
     SELECT 'c' ,'c-details' ,'3' FROM DUAL
     )
SELECT NVL(val1,'Total Result'),
     val2,
     SUM(val3) tot,
     grouping(val1),
     grouping(val2)
from data
group by ROLLUP(val1, val2);

输出:

NVL(VAL1,'TOTALRESULT') VAL2 TOT 分组(VAL1) 分组(VAL2)
------------ --------- ---------- -------- ------ --------------
a a-详细信息 1 0 0
一个 1 0 1
b b-详细信息 2 0 0
b 2 0 1
c c-详细信息 3 0 0
c 3 0 1
总结果 6 1 1

因此,您的查询应如下所示:

WITH data AS
     ( SELECT 'a' AS val1 ,'a-details' AS val2 , '1' AS val3 FROM DUAL
     UNION ALL
     SELECT 'b' ,'b-details' ,'2' FROM DUAL
     UNION ALL
     SELECT 'c' ,'c-details' ,'3' FROM DUAL
     )
SELECT NVL(val1,'Total Result'),
     val2,
     SUM(val3) tot
from data
group by ROLLUP(val1, val2)
HAVING GROUPING(val1) = 1
   OR (GROUPING(val1) + GROUPING(val2) = 0);

输出:

NVL(VAL1,'TOTALRESULT') VAL2 TOT
------------ --------- ----------
a-详细信息 1
b b-详细信息 2
c c-详细信息 3
总成绩 6

使用GROUPINGAskTom 功能的想法,请点击此处

于 2013-11-19T10:03:37.343 回答
11

我发现使用 GROUPING SET 子句指定我需要的确切集合相当容易:

WITH data(val1, val2, val3) AS
     ( SELECT 'a' ,'a-details' ,'1' FROM DUAL
     UNION ALL
     SELECT 'b' ,'b-details' ,'2' FROM DUAL
     UNION ALL
     SELECT 'c' ,'c-details' ,'3' FROM DUAL
     )
SELECT NVL(val1,'Total Result'),
     val2,
     SUM(val3) tot
from data
group by grouping sets ((val1, val2),());

我怀疑它更有效,因为它直接指定要计算的级别。

http://sqlfiddle.com/#!4/8301d/3

CUBE 和 ROLLUP 可以方便地自动生成大量聚合级别(例如,维度层次结构中的每个级别),如果您想从大型 CUBE 生成的级别中删除一小部分级别,则可能需要使用 GROUPING ID set,但 GROUPING SET 是专门为指定特定的聚合级别而设计的。

于 2013-11-19T13:41:53.217 回答