Использование ROLL UP / CUBE в сочетании с PIVOT [Oracle] - PullRequest
1 голос
/ 18 апреля 2019

У меня есть таблица в 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 Ответ

1 голос
/ 18 апреля 2019

При группировке по 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

демо


Edit:

Если в столбцах суммирования вам нужны суммы различных подсчетов, сначала выполните базовую группировку, затем используйте куб. И разворот в конце. Агрегирующая функция в сводной таблице не важна, поскольку вы уже подсчитали значения, по одному на каждую строку / столбец.

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
...