그룹 집계 필요성
실무에서는 데이터를 단순히 나열하는 것만으로는 부족합니다.
그룹별로 요약된 통계 정보를 구해야 할 때가 많습니다.
예를 들어,
- "부서별 평균 급여는 어떻게 되지?"
- "직급별 인원 수를 알고 싶어."
- "부서와 직급별 급여 총합이 필요해."
이런 요구사항을 처리하기 위해 사용하는 것이 바로 GROUP BY이며,
이 기능을 확장한 것이 ROLLUP, CUBE, GROUPING SETS입니다.
ROLLUP – 계층적 집계
ROLLUP은 위계(hierarchy) 구조를 기준으로 단계적으로 요약 집계를 해주는 기능입니다.
쉽게 말하면, 상위 → 하위 항목 순으로 점차 집계를 생략하며 총합을 계산합니다.
목적
- 부서 → 직급 → 전체 총합처럼 단계적 요약이 필요한 경우
- 보고서나 대시보드에서 요약 레벨별로 데이터를 보고 싶을 때
예시
SELECT 부서, 직급, SUM(급여)
FROM 직원
GROUP BY ROLLUP (부서, 직급);
📌 위 쿼리는 다음과 같은 집계를 수행합니다.
- 부서 + 직급별 급여 합계
- 부서별 총합 (직급 생략)
- 전체 총합 (부서, 직급 모두 생략)
💡 이처럼 ROLLUP은 그룹 컬럼을 뒤에서부터 하나씩 생략해가며 집계를 수행합니다.
즉, (부서, 직급) → (부서) → () 순
| 부서 | 직급 | 급여 합계 |
| 영업팀 | 사원 | 2,000 |
| 영업팀 | 대리 | 2,500 |
| 영업팀 | NULL | 4,500 |
| 개발팀 | 사원 | 3,000 |
| 개발팀 | 대리 | 3,500 |
| 개발팀 | NULL | 6,500 |
| NULL | NULL | 11,000 |
✅ 계층 구조로 집계할 때 매우 유용한 기능입니다.
CUBE – 가능한 모든 조합 집계
CUBE는 지정한 컬럼의 모든 가능한 조합을 집계합니다.
즉, (부서, 직급)에 대해 가능한 모든 부분 집합을 모두 계산해 줍니다.
예시
SELECT 부서, 직급, SUM(급여)
FROM 직원
GROUP BY CUBE (부서, 직급);
📌 위 쿼리는 다음 4가지 집계를 수행합니다.
- 부서 + 직급
- 부서별
- 직급별
- 전체 총합
📝 n개의 열이 있다면 2ⁿ개의 집계 결과가 생성됩니다.
즉, 열이 많아질수록 결과가 기하급수적으로 많아지므로 주의가 필요합니다.
GROUPING SETS – 직접 집계 조합 지정
GROUPING SETS는 필요한 집계 조합만 직접 선택할 수 있는 방식입니다.
ROLLUP, CUBE보다 훨씬 유연하게 집계를 제어할 수 있습니다.
예시
SELECT 부서, 직급, SUM(급여)
FROM 직원
GROUP BY GROUPING SETS (
(부서),
(직급),
(부서, 직급),
()
);
📌 이 쿼리는 다음과 같은 집계를 수행합니다.
- 부서별
- 직급별
- 부서 + 직급
- 전체 총합
⚠ 일부 DBMS에서는 GROUP BY ()가 지원되지 않거나 문법이 다를 수 있으므로 사전에 확인이 필요합니다.
✅ 가장 유연한 집계 방식이며, 불필요한 조합은 빼고 필요한 조합만 골라서 집계할 수 있습니다.
GROUP BY + UNION 방식은 비효율적
과거에는 아래처럼 GROUP BY와 UNION을 조합해서 여러 형태의 집계를 만들기도 했습니다.
SELECT 부서, NULL AS 직급, SUM(급여)
FROM 직원
GROUP BY 부서
UNION ALL
SELECT NULL AS 부서, 직급, SUM(급여)
FROM 직원
GROUP BY 직급
UNION ALL
SELECT 부서, 직급, SUM(급여)
FROM 직원
GROUP BY 부서, 직급
UNION ALL
SELECT NULL, NULL, SUM(급여)
FROM 직원;
하지만 이 방식은...
- 📉 중복 제거 및 성능 저하 위험
- 😵💫 쿼리 가독성 저하
- 🧹 유지보수 어려움
이런 이유로 실무에서는 잘 사용하지 않으며,
대신 GROUPING SETS로 더 간단하고 효율적으로 처리할 수 있습니다.
참고: GROUPING() 함수로 집계 구분하기
ROLLUP, CUBE, GROUPING SETS를 사용하면 결과에 NULL이 생기기 때문에
어떤 행이 실제 데이터인지, 어떤 행이 집계된 결과인지 구분이 필요할 수 있습니다.
이럴 때 GROUPING() 함수를 사용합니다.
SELECT 부서, 직급,
GROUPING(부서) AS 부서집계여부,
GROUPING(직급) AS 직급집계여부,
SUM(급여)
FROM 직원
GROUP BY CUBE (부서, 직급);
- GROUPING(컬럼)은 해당 컬럼이 집계된 항목이면 1, 아니면 0을 반환합니다.
정리
| 기능 유형 | 설명 | 집계 범위 예시 | 유연성 | 특징 |
| ROLLUP | 계층적 집계 | (부서, 직급), (부서), () | 중간 | 위계 순서대로 부분 집계 |
| CUBE | 모든 조합 집계 | (부서), (직급), (부서, 직급), () | 낮음 | 가능한 모든 부분 집합 계산 |
| GROUPING SETS | 직접 조합 지정 | 원하는 조합만 지정 | 높음 | 가장 유연한 집계 방식 |
| GROUP BY + UNION | 수동 조합 방식 (비추천) | 직접 코딩 필요 | 매우 낮음 | 성능 저하 및 유지보수 어려움 |