Using Advanced Grouping

1. Using GROUPING SETS

SELECT country, tier, count(*)
  FROM customers
 GROUP BY GROUPING SETS ((country, tier), (country), (tier), ());
SetMeaning
(a, b)Group by both
(a)Subtotal by a
()Grand total

2. Using ROLLUP

SELECT year, quarter, sum(revenue)
  FROM sales GROUP BY ROLLUP (year, quarter);
-- Equivalent to GROUPING SETS ((year,quarter),(year),())

3. Using CUBE

SELECT region, product, sum(revenue)
  FROM sales GROUP BY CUBE (region, product);
-- All 2^n combinations
ConstructSubgroups Generated
ROLLUP(a,b,c)n+1 levels (hierarchy)
CUBE(a,b,c)2^n combinations
GROUPING SETSExplicit list

4. Using GROUPING Function

SELECT
   coalesce(country,'(all)') AS country,
   coalesce(tier,'(all)')    AS tier,
   GROUPING(country, tier)   AS gid,    -- bitmask
   count(*)
  FROM customers GROUP BY ROLLUP (country, tier);
GROUPING(col) ReturnsMeaning
0Column is in grouping set
1Column is aggregated away (subtotal)

5. Combining GROUPING SETS with FILTER

SELECT country, tier,
       count(*) FILTER (WHERE active),
       count(*) FILTER (WHERE NOT active)
  FROM customers GROUP BY GROUPING SETS ((country, tier),(country),());

6. Using Empty Grouping Set

SELECT count(*) FROM orders GROUP BY GROUPING SETS (());
Note: () in grouping sets produces a single grand-total row even when normal GROUP BY would yield none.

7. Understanding GROUPING SETS vs UNION ALL

AspectGROUPING SETSUNION ALL
ScansSingle scanOne per query
CostLowerHigher
ReadabilityCompactVerbose

8. Optimizing Advanced Grouping Queries

TacticEffect
Pre-aggregateUse materialized view for base groups
IndexesBRIN/btree on group keys
enable_hashaggKeep on; usually fastest
work_memBump to avoid disk spill
Parallel aggregateEnable for large fact tables