It often happens that a query will have a group A which is a superset of group B which in turn is a superset of group C. When aggregates are required at each level a query like this can be used.
set null '(null)'
select
grp_a
, grp_b
, grp_c
, count(*)
from
t
group by
grouping sets
(
( grp_a, grp_b, grp_c )
, ( grp_a, grp_b )
, ( grp_a )
, ()
)
order by
1, 2, 3
;
GRP_A GRP_B GRP_C COUNT(*) ---------- ---------- ---------- ---------- a1 b1 c1 2 a1 b1 (null) 2 a1 b2 c1 2 a1 b2 c2 1 a1 b2 (null) 3 a1 (null) (null) 5 a2 b3 c2 3 a2 b3 (null) 3 a2 (null) (null) 3 (null) (null) (null) 8
This arrangement is common enough that SQL actually provides a shortcut for specifying these types of GROUPING SETS clauses. It uses the ROLLUP operator. Here is how the query above looks when implemented with ROLLUP.
select grp_a , grp_b , grp_c , count(*) from t group by ROLLUP( GRP_A, GRP_B, GRP_C ) order by 1, 2, 3 ;
GRP_A GRP_B GRP_C COUNT(*) ---------- ---------- ---------- ---------- a1 b1 c1 2 a1 b1 (null) 2 a1 b2 c1 2 a1 b2 c2 1 a1 b2 (null) 3 a1 (null) (null) 5 a2 b3 c2 3 a2 b3 (null) 3 a2 (null) (null) 3 (null) (null) (null) 8
