【问题标题】:oracle rollup function with multiple columns具有多列的 oracle 汇总函数
【发布时间】:2013-11-19 09:42:12
【问题描述】:

我有一个简单的查询:

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 

提前致谢。

【问题讨论】:

    标签: sql oracle rollup


    【解决方案1】:

    我发现使用 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 可以方便地自动生成大量聚合级别(例如,维度层次结构中的每个级别),如果您想从大数据中删除一小部分级别,则可能需要使用 GROUPING ID CUBE 生成的集合,但 GROUPING SET 是专门为指定特定聚合级别而设计的。

    【讨论】:

    • 感谢@David Aldrige。所以这对我来说现在是一个新的学习主题。
    【解决方案2】:

    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 

    Check at SQLFiddle

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

    编辑

    分组功能

    关于评论。你可以使用GROUPING函数:

    GROUPING - 接受单个列作为参数并返回“1”如果 该列包含一个空值,该空值作为小计的一部分由 ROLLUPCUBE 操作或“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

    使用 AskTom 的 GROUPING 函数的想法,here

    【讨论】:

    • @Przemyslaw Kruglej,请告诉我要使用查询而不是明确使用 (0,3) ,因为我需要更改添加列。
    • @ajmalmhd04 我认为您应该接受 David Aldridge 的回答。我不知道你可以用GORUPING SETS 做到这一点。
    • @PrzemyslawKruglej,感谢您的回答。将了解有关 GROUPING 的更多信息。无论如何,你已经为我 +1 了 :)。
    猜你喜欢
    • 2019-09-29
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    相关资源
    最近更新 更多