빠른 비교
-- 필요한 집계 조합을 직접 지정
GROUP BY GROUPING SETS ((region, product), (region), ())
-- 계층형 소계: region, region+product, 전체
GROUP BY ROLLUP (region, product)
-- 가능한 모든 조합: region, product, region+product, 전체
GROUP BY CUBE (region, product)| 문법 | 생성되는 집계 |
|---|---|
GROUPING SETS | 지정한 조합만 |
ROLLUP | 왼쪽부터 계층적으로 줄어드는 소계 |
CUBE | 지정 컬럼의 모든 조합 |
문법
GROUPING SETS는 여러 GROUP BY를 하나로 묶는다
GROUPING SETS는 같은 원본 행을 기준으로 여러 그룹 조합을 계산합니다. 지역과 상품별 매출, 지역별 매출, 전체 매출을 각각 별도 쿼리와 UNION ALL로 합치지 않아도 한 번의 집계 문법으로 표현할 수 있습니다.
SELECT
region,
product,
sum(amount) AS revenue
FROM sales
GROUP BY GROUPING SETS (
(region, product),
(region),
()
)
ORDER BY region, product;빈 그룹 ()은 전체 행을 하나의 그룹으로 묶는 총계를 의미합니다. 특정 grouping set에 포함되지 않은 컬럼은 결과에서 NULL로 채워집니다.
ROLLUP은 계층형 소계에 맞다
ROLLUP (region, product)는 (region, product), (region), () 순서의 집계를 만듭니다. 왼쪽 컬럼이 더 큰 분류이고 오른쪽 컬럼이 그 안의 세부 분류일 때 자연스럽습니다.
SELECT
region,
product,
sum(amount) AS revenue
FROM sales
GROUP BY ROLLUP (region, product);ROLLUP (year, month, day)처럼 시간 계층을 다룰 때도 적합합니다. 반대로 컬럼 사이에 계층 관계가 없으면 ROLLUP보다 GROUPING SETS나 CUBE가 더 명확할 수 있습니다.
CUBE는 가능한 모든 축 조합을 계산한다
CUBE (region, product)는 (region, product), (region), (product), () 조합을 모두 만듭니다. 대시보드에서 여러 분석 축을 자유롭게 전환해야 할 때 유용하지만, 컬럼 수가 늘수록 결과 조합이 빠르게 증가합니다.
SELECT
region,
product,
sum(amount) AS revenue
FROM sales
GROUP BY CUBE (region, product);분석 축이 4개면 최대 16개 grouping set이 생깁니다. 원본 데이터가 크고 축 조합이 많으면 실행 시간과 결과 행 수가 모두 커지므로 필요한 조합만 GROUPING SETS로 제한하는 편이 낫습니다.
GROUPING 함수는 실제 NULL과 소계 NULL을 구분한다
소계 행에서는 grouping set에 포함되지 않은 컬럼이 NULL로 표시됩니다. 그런데 원본 데이터에도 실제 NULL이 있을 수 있으므로, 소계 행인지 원본 NULL 그룹인지 구분하려면 GROUPING()을 함께 사용합니다.
SELECT
region,
product,
GROUPING(region) AS g_region,
GROUPING(product) AS g_product,
sum(amount) AS revenue
FROM sales
GROUP BY ROLLUP (region, product);GROUPING(product) = 1이면 해당 결과 행에서 product가 grouping set에 포함되지 않았다는 뜻입니다. 표시용 라벨을 만들 때는 단순 COALESCE(product, '전체')만 쓰지 말고 GROUPING() 결과를 함께 봐야 합니다.
선택 기준
| 상황 | 적합한 선택 |
|---|---|
| 필요한 소계 조합이 명확함 | GROUPING SETS |
| 상위, 하위 분류가 계층적임 | ROLLUP |
| 모든 분석 축 조합이 필요함 | CUBE |
| 실제 NULL과 소계 NULL을 구분해야 함 | GROUPING() |
| 조합 수가 많고 데이터가 큼 | 필요한 grouping set만 명시 |
월별, 상품별, 전체 합계처럼 보고서 행을 한 번에 만들 때 유용합니다. 다만 애플리케이션에서 각 집계를 서로 다른 캐시 정책으로 다루거나, 각 집계마다 필터 조건이 크게 다르면 별도 쿼리로 나누는 편이 운영상 단순할 수 있습니다.
주의할 점
CUBE는 컬럼 수에 따라 grouping set 수가 기하급수적으로 늘어납니다. 모든 조합이 실제로 필요한지 확인하지 않고 사용하면 결과 행 수와 정렬 비용이 예상보다 커질 수 있습니다.
-- 결과 조합이 많아질 수 있음
GROUP BY CUBE (region, product, channel, month)
-- 필요한 조합만 명시
GROUP BY GROUPING SETS (
(region, product),
(region, channel),
(month),
()
)소계 행의 NULL은 원본 데이터의 NULL과 같은 모양으로 보입니다. 보고서에서 NULL을 모두 "전체"로 바꾸면 실제 미분류 데이터가 총계처럼 보일 수 있으므로 GROUPING()으로 구분해야 합니다.
참고 링크
2 sources