将 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
编辑:
如果在对列求和时需要不同计数的总和,那么首先进行基本分组,然后使用立方体。并在最后转动。 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
我在 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
编辑:
如果在对列求和时需要不同计数的总和,那么首先进行基本分组,然后使用立方体。并在最后转动。 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