postgresql 的 group by 之 grouping sets/rollup/cube
postgresql 从 9.5 开始提供 rollup/cube/grouping sets 分组函数,使用起来更为方便,尤其时用sql直接出报表时,一个sql就把明细和汇总值全部搞定。
https://www.postgresql.org/docs/9.5/static/sql-select.html
https://www.postgresql.org/docs/9.5/static/queries-table-expressions.html#QUERIES-GROUPING-SETS
and grouping_element can be one of:
( )
expression
( expression [, ...] )
ROLLUP ( { expression | ( expression [, ...] ) } [, ...] )
CUBE ( { expression | ( expression [, ...] ) } [, ...] )
GROUPING SETS ( grouping_element [, ...] )
测试数据
with tmp_tab as (
select '20180205' as day_id,'1001' as custno,'a001' as data_type,1 as qty union all
select '20180205' as day_id,'1001' as custno,'a002' as data_type,2 as qty union all
select '20180205' as day_id,'1002' as custno,'a001' as data_type,3 as qty union all
select '20180205' as day_id,'1002' as custno,'a003' as data_type,4 as qty union all
select '20180206' as day_id,'1001' as custno,'a004' as data_type,5 as qty union all
select '20180207' as day_id,'1003' as custno,'a001' as data_type,6 as qty
)
select grouping(t0.day_id) as day_id,
grouping(t0.data_type) as data_type,
grouping(t0.custno) as custno,
t0.day_id,
t0.data_type,
t0.custno,
sum(t0.qty)
from tmp_tab t0
group by t0.day_id,t0.data_type,t0.custno
grouping sets:显示指定的汇总值
1、group by grouping sets ( (t0.day_id,t0.data_type,t0.custno) )
等效于
group by t0.day_id,t0.data_type,t0.custno
day_id | data_type | custno | day_id | data_type | custno | sum
--------+-----------+--------+----------+-----------+--------+-----
0 | 0 | 0 | 20180205 | a001 | 1001 | 1
0 | 0 | 0 | 20180207 | a001 | 1003 | 6
0 | 0 | 0 | 20180205 | a002 | 1001 | 2
0 | 0 | 0 | 20180205 | a001 | 1002 | 3
0 | 0 | 0 | 20180205 | a003 | 1002 | 4
0 | 0 | 0 | 20180206 | a004 | 1001 | 5
(6 rows)
2、group by grouping sets ( t0.day_id,t0.data_type,t0.custno )
对 t0.day_id,t0.data_type,t0.custno 这三列分别求合计
day_id | data_type | custno | day_id | data_type | custno | sum
--------+-----------+--------+----------+-----------+--------+-----
0 | 1 | 1 | 20180205 | | | 10
0 | 1 | 1 | 20180206 | | | 5
0 | 1 | 1 | 20180207 | | | 6
1 | 1 | 0 | | | 1001 | 8
1 | 1 | 0 | | | 1002 | 7
1 | 1 | 0 | | | 1003 | 6
1 | 0 | 1 | | a001 | | 10
1 | 0 | 1 | | a002 | | 2
1 | 0 | 1 | | a003 | | 4
1 | 0 | 1 | | a004 | | 5
(10 rows)
3、group by grouping sets ( (t0.day_id,t0.data_type),t0.custno )
(t0.day_id,t0.data_type) 作为一个整体求合计
day_id | data_type | custno | day_id | data_type | custno | sum
--------+-----------+--------+----------+-----------+--------+-----
1 | 1 | 0 | | | 1001 | 8
1 | 1 | 0 | | | 1002 | 7
1 | 1 | 0 | | | 1003 | 6
0 | 0 | 1 | 20180205 | a001 | | 4
0 | 0 | 1 | 20180205 | a002 | | 2
0 | 0 | 1 | 20180205 | a003 | | 4
0 | 0 | 1 | 20180206 | a004 | | 5
0 | 0 | 1 | 20180207 | a001 | | 6
(8 rows)
4、group by grouping sets ( (t0.day_id),(t0.data_type),(t0.custno) )
day_id | data_type | custno | day_id | data_type | custno | sum
--------+-----------+--------+----------+-----------+--------+-----
0 | 1 | 1 | 20180205 | | | 10
0 | 1 | 1 | 20180206 | | | 5
0 | 1 | 1 | 20180207 | | | 6
1 | 1 | 0 | | | 1001 | 8
1 | 1 | 0 | | | 1002 | 7
1 | 1 | 0 | | | 1003 | 6
1 | 0 | 1 | | a001 | | 10
1 | 0 | 1 | | a002 | | 2
1 | 0 | 1 | | a003 | | 4
1 | 0 | 1 | | a004 | | 5
(10 rows)
rollup:保留 group by 的基础上,增加汇总行
1、group by rollup ( (t0.day_id,t0.data_type,t0.custno) )
对t0.day_id,t0.data_type,t0.custno 这三列整体求个合计
day_id | data_type | custno | day_id | data_type | custno | sum
--------+-----------+--------+----------+-----------+--------+-----
0 | 0 | 0 | 20180205 | a001 | 1001 | 1
0 | 0 | 0 | 20180205 | a001 | 1002 | 3
0 | 0 | 0 | 20180205 | a002 | 1001 | 2
0 | 0 | 0 | 20180205 | a003 | 1002 | 4
0 | 0 | 0 | 20180206 | a004 | 1001 | 5
0 | 0 | 0 | 20180207 | a001 | 1003 | 6
1 | 1 | 1 | | | | 21
(7 rows)
2、group by rollup ( t0.day_id,t0.data_type,t0.custno )
对t0.day_id,t0.data_type,t0.custno 依次求合计
day_id | data_type | custno | day_id | data_type | custno | sum
--------+-----------+--------+----------+-----------+--------+-----
0 | 0 | 0 | 20180205 | a001 | 1001 | 1
0 | 0 | 0 | 20180205 | a001 | 1002 | 3
0 | 0 | 1 | 20180205 | a001 | | 4
0 | 0 | 0 | 20180205 | a002 | 1001 | 2
0 | 0 | 1 | 20180205 | a002 | | 2
0 | 0 | 0 | 20180205 | a003 | 1002 | 4
0 | 0 | 1 | 20180205 | a003 | | 4
0 | 1 | 1 | 20180205 | | | 10
0 | 0 | 0 | 20180206 | a004 | 1001 | 5
0 | 0 | 1 | 20180206 | a004 | | 5
0 | 1 | 1 | 20180206 | | | 5
0 | 0 | 0 | 20180207 | a001 | 1003 | 6
0 | 0 | 1 | 20180207 | a001 | | 6
0 | 1 | 1 | 20180207 | | | 6
1 | 1 | 1 | | | | 21
(15 rows)
3、group by rollup ( (t0.day_id,t0.data_type),t0.custno )
(t0.day_id,t0.data_type) 作为一个整体求合计
day_id | data_type | custno | day_id | data_type | custno | sum
--------+-----------+--------+----------+-----------+--------+-----
0 | 0 | 0 | 20180205 | a001 | 1001 | 1
0 | 0 | 0 | 20180205 | a001 | 1002 | 3
0 | 0 | 1 | 20180205 | a001 | | 4
0 | 0 | 0 | 20180205 | a002 | 1001 | 2
0 | 0 | 1 | 20180205 | a002 | | 2
0 | 0 | 0 | 20180205 | a003 | 1002 | 4
0 | 0 | 1 | 20180205 | a003 | | 4
0 | 0 | 0 | 20180206 | a004 | 1001 | 5
0 | 0 | 1 | 20180206 | a004 | | 5
0 | 0 | 0 | 20180207 | a001 | 1003 | 6
0 | 0 | 1 | 20180207 | a001 | | 6
1 | 1 | 1 | | | | 21
(12 rows)
4、group by rollup ( (t0.day_id),(t0.data_type),(t0.custno) )
等效于第二种情况
group by rollup ( t0.day_id,t0.data_type,t0.custno )
day_id | data_type | custno | day_id | data_type | custno | sum
--------+-----------+--------+----------+-----------+--------+-----
0 | 0 | 0 | 20180205 | a001 | 1001 | 1
0 | 0 | 0 | 20180205 | a001 | 1002 | 3
0 | 0 | 1 | 20180205 | a001 | | 4
0 | 0 | 0 | 20180205 | a002 | 1001 | 2
0 | 0 | 1 | 20180205 | a002 | | 2
0 | 0 | 0 | 20180205 | a003 | 1002 | 4
0 | 0 | 1 | 20180205 | a003 | | 4
0 | 1 | 1 | 20180205 | | | 10
0 | 0 | 0 | 20180206 | a004 | 1001 | 5
0 | 0 | 1 | 20180206 | a004 | | 5
0 | 1 | 1 | 20180206 | | | 5
0 | 0 | 0 | 20180207 | a001 | 1003 | 6
0 | 0 | 1 | 20180207 | a001 | | 6
0 | 1 | 1 | 20180207 | | | 6
1 | 1 | 1 | | | | 21
(15 rows)
cube:保留 group by 的基础上,增加指定列的交叉汇总行
1、group by cube ( (t0.day_id,t0.data_type,t0.custno) )
day_id | data_type | custno | day_id | data_type | custno | sum
--------+-----------+--------+----------+-----------+--------+-----
0 | 0 | 0 | 20180205 | a001 | 1001 | 1
0 | 0 | 0 | 20180205 | a001 | 1002 | 3
0 | 0 | 0 | 20180205 | a002 | 1001 | 2
0 | 0 | 0 | 20180205 | a003 | 1002 | 4
0 | 0 | 0 | 20180206 | a004 | 1001 | 5
0 | 0 | 0 | 20180207 | a001 | 1003 | 6
1 | 1 | 1 | | | | 21
(7 rows)
2、group by cube ( t0.day_id,t0.data_type,t0.custno )
t0.day_id,t0.data_type,t0.custno 这三列交叉汇总
day_id | data_type | custno | day_id | data_type | custno | sum
--------+-----------+--------+----------+-----------+--------+-----
0 | 0 | 0 | 20180205 | a001 | 1001 | 1
0 | 0 | 0 | 20180205 | a001 | 1002 | 3
0 | 0 | 1 | 20180205 | a001 | | 4
0 | 0 | 0 | 20180205 | a002 | 1001 | 2
0 | 0 | 1 | 20180205 | a002 | | 2
0 | 0 | 0 | 20180205 | a003 | 1002 | 4
0 | 0 | 1 | 20180205 | a003 | | 4
0 | 1 | 1 | 20180205 | | | 10
0 | 0 | 0 | 20180206 | a004 | 1001 | 5
0 | 0 | 1 | 20180206 | a004 | | 5
0 | 1 | 1 | 20180206 | | | 5
0 | 0 | 0 | 20180207 | a001 | 1003 | 6
0 | 0 | 1 | 20180207 | a001 | | 6
0 | 1 | 1 | 20180207 | | | 6
1 | 1 | 1 | | | | 21
0 | 1 | 0 | 20180205 | | 1001 | 3
0 | 1 | 0 | 20180206 | | 1001 | 5
1 | 1 | 0 | | | 1001 | 8
0 | 1 | 0 | 20180205 | | 1002 | 7
1 | 1 | 0 | | | 1002 | 7
0 | 1 | 0 | 20180207 | | 1003 | 6
1 | 1 | 0 | | | 1003 | 6
1 | 0 | 0 | | a001 | 1001 | 1
1 | 0 | 0 | | a001 | 1002 | 3
1 | 0 | 0 | | a001 | 1003 | 6
1 | 0 | 1 | | a001 | | 10
1 | 0 | 0 | | a002 | 1001 | 2
1 | 0 | 1 | | a002 | | 2
1 | 0 | 0 | | a003 | 1002 | 4
1 | 0 | 1 | | a003 | | 4
1 | 0 | 0 | | a004 | 1001 | 5
1 | 0 | 1 | | a004 | | 5
(32 rows)
3、group by cube ( (t0.day_id,t0.data_type),t0.custno )
day_id | data_type | custno | day_id | data_type | custno | sum
--------+-----------+--------+----------+-----------+--------+-----
0 | 0 | 0 | 20180205 | a001 | 1001 | 1
0 | 0 | 0 | 20180205 | a002 | 1001 | 2
0 | 0 | 0 | 20180206 | a004 | 1001 | 5
1 | 1 | 0 | | | 1001 | 8
0 | 0 | 0 | 20180205 | a001 | 1002 | 3
0 | 0 | 0 | 20180205 | a003 | 1002 | 4
1 | 1 | 0 | | | 1002 | 7
0 | 0 | 0 | 20180207 | a001 | 1003 | 6
1 | 1 | 0 | | | 1003 | 6
1 | 1 | 1 | | | | 21
0 | 0 | 1 | 20180205 | a001 | | 4
0 | 0 | 1 | 20180205 | a002 | | 2
0 | 0 | 1 | 20180205 | a003 | | 4
0 | 0 | 1 | 20180206 | a004 | | 5
0 | 0 | 1 | 20180207 | a001 | | 6
(15 rows)
4、group by cube ( (t0.day_id),(t0.data_type),(t0.custno) )
day_id | data_type | custno | day_id | data_type | custno | sum
--------+-----------+--------+----------+-----------+--------+-----
0 | 0 | 0 | 20180205 | a001 | 1001 | 1
0 | 0 | 0 | 20180205 | a001 | 1002 | 3
0 | 0 | 1 | 20180205 | a001 | | 4
0 | 0 | 0 | 20180205 | a002 | 1001 | 2
0 | 0 | 1 | 20180205 | a002 | | 2
0 | 0 | 0 | 20180205 | a003 | 1002 | 4
0 | 0 | 1 | 20180205 | a003 | | 4
0 | 1 | 1 | 20180205 | | | 10
0 | 0 | 0 | 20180206 | a004 | 1001 | 5
0 | 0 | 1 | 20180206 | a004 | | 5
0 | 1 | 1 | 20180206 | | | 5
0 | 0 | 0 | 20180207 | a001 | 1003 | 6
0 | 0 | 1 | 20180207 | a001 | | 6
0 | 1 | 1 | 20180207 | | | 6
1 | 1 | 1 | | | | 21
0 | 1 | 0 | 20180205 | | 1001 | 3
0 | 1 | 0 | 20180206 | | 1001 | 5
1 | 1 | 0 | | | 1001 | 8
0 | 1 | 0 | 20180205 | | 1002 | 7
1 | 1 | 0 | | | 1002 | 7
0 | 1 | 0 | 20180207 | | 1003 | 6
1 | 1 | 0 | | | 1003 | 6
1 | 0 | 0 | | a001 | 1001 | 1
1 | 0 | 0 | | a001 | 1002 | 3
1 | 0 | 0 | | a001 | 1003 | 6
1 | 0 | 1 | | a001 | | 10
1 | 0 | 0 | | a002 | 1001 | 2
1 | 0 | 1 | | a002 | | 2
1 | 0 | 0 | | a003 | 1002 | 4
1 | 0 | 1 | | a003 | | 4
1 | 0 | 0 | | a004 | 1001 | 5
1 | 0 | 1 | | a004 | | 5
(32 rows)
postgresql 的 grouping sets/rollup/cube 与 oracle 的是一样的,使用简单,功能强大。