将ROLL UP / CUBE与PIVOT [Oracle]

时间:2019-04-18 08:38:02

标签: sql oracle group-by rollup

我在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。

1 个答案:

答案 0 :(得分: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