【问题标题】:Using ROLL UP/CUBE in conjunction with PIVOT [Oracle]将 ROLL UP/CUBE 与 PIVOT [Oracle] 结合使用
【发布时间】:2019-09-08 13:32:57
【问题描述】:

我在 Oracle 中有一个如下所示的表:

year    month   customer
------------------------
2011    Jan     Smith
2011    Jan     Smith
2012    Feb     Howard
2013    Feb     Howard
...

现在我想变成这样:

year    Jan     Feb     ...     Dec     ytotal
-----------------------------------------------
2011    3       1       ...     5       27
2012    1       4       ...     11      45
...                                     ...
2018    9       1       ...     1       21
mtotal  35      19              51      275 

每个单元格中的数字对应于客户姓名的 DISTINCT 计数。

当我尝试执行此查询时:

SELECT DECODE(GROUPING(year), 1, 'mtotal:', year) year,
       DECODE(GROUPING(month), 1, 'ytotal:', month) month,
       COUNT(DISTINCT customer) AS cust_count
FROM mytable
GROUP BY ROLLUP(year, month)

我得到这个中间结果:

year    month   cust_count
--------------------------
2011    Jan     3
2011    Feb     1
...
2011    Dec     5
2011    ytotal  27
2012    Jan     1
2012    Feb     4
...
2012    Dec     11
2012    ytotal  45
...
2018    Jan     9
2018    Feb     1
...
2018    Dec     1
2018    ytotal  21
mtotal  ytotal  275

当我将其用作子查询时,请执行枢轴:

SELECT * FROM (
    SELECT DECODE(GROUPING(year), 1, 'mtotal:', year) year,
           DECODE(GROUPING(month), 1, 'ytotal:', month) month,
           COUNT(DISTINCT customer) AS cust_count
    FROM mytable
    GROUP BY ROLLUP(year, month)
) 
PIVOT (
    COUNT(month) FOR month IN ('Jan', 'Feb', ..., 'Dec', 'ytotal')
)

我没有得到预期的结果。请在答案中包含 ROLL UP/CUBE 和 PIVOT 的使用。

【问题讨论】:

    标签: sql oracle group-by rollup


    【解决方案1】:

    通过rollup(year, month) 分组,您没有不同年份的同一个月的总和。所以我使用了cube并稍微修改了您的查询,请检查:

    select * 
      from (select case when grouping(year)  = 1 then 'ysum' else to_char(year) end year,
                   case when grouping(month) = 1 then 'msum' else to_char(month) end month,
                   count(distinct customer) as cnt
              from mytable
              group by cube(year, month) )
      pivot (sum(cnt) for month in ('Jan', 'Feb', 'Dec', 'msum'))
      order by year
    

    demo


    编辑:

    如果在求和列中需要不同计数的总和,则首先进行基本分组,然后使用多维数据集。并在最后转动。透视中的聚合函数并不重要,因为您已经计算了值,每行/列一个。

    select * 
      from (
        select nvl(to_char(year), 'ys') year, nvl(to_char(month), 'ms') month, sum(cnt) cnt
          from (
            select year, month, count(distinct customer) cnt 
              from mytable 
              group by year, month)
          group by cube(year, month))
      pivot (sum(cnt) for month in ('Jan', 'Feb', 'Dec', 'ms')) 
      order by year
    

    【讨论】:

    • 最后一行和最后一列的求和不正确
    • 显示不同客户的数量。如果只有一个,每个月都一样,那么在总和列中我们看到 1,而不是 12。如果你想要总和,可以使用联合来完成。
    猜你喜欢
    • 1970-01-01
    • 2021-10-19
    • 2016-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多