将 ROLL UP/CUBE 与 PIVOT [Oracle] 结合使用

Using ROLL UP/CUBE in conjunction with PIVOT [Oracle]

我在 Oracle 中有一个 table,如下所示:

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 的使用。

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


编辑:

如果在对列求和时需要不同计数的总和,那么首先进行基本分组,然后使用立方体。并在最后转动。 pivot 中的聚合函数并不重要,因为您已经计算了值,每行/列一个。

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