2과목 · SQL 기본 및 활용·9장
GROUP BY · HAVING
GROUP BY의 의미, HAVING의 역할, ROLLUP·CUBE·GROUPING SETS 확장 집계를 다룹니다.
1. GROUP BY의 의미
GROUP BY는 행을 지정된 컬럼 값이 같은 것끼리 묶어 그룹을 만들고, 각 그룹에 집계 함수를 적용합니다.
SELECT dept_id, COUNT(*) AS cnt, AVG(salary) AS avg_sal
FROM emp
GROUP BY dept_id;
규칙
SELECT리스트에는 GROUP BY에 나열된 컬럼 또는 집계 함수만 올 수 있다.GROUP BY여러 컬럼 지정 시 "여러 컬럼 조합이 같은 행끼리" 그룹화.
SELECT dept_id, job, COUNT(*) FROM emp GROUP BY dept_id, job;
2. HAVING — 그룹 필터
HAVING은 GROUP BY 결과 중 조건을 만족하는 그룹만 남긴다. WHERE가 행 필터라면 HAVING은 그룹 필터.
SELECT dept_id, AVG(salary) AS avg_sal
FROM emp
WHERE hired_at >= DATE '2020-01-01' -- 행 단위 필터
GROUP BY dept_id
HAVING AVG(salary) >= 4000000; -- 그룹 단위 필터
WHERE vs HAVING
| 구분 | 위치 | 대상 | 집계 함수 |
|---|---|---|---|
WHERE |
GROUP BY 전 | 개별 행 | 사용 불가 |
HAVING |
GROUP BY 후 | 그룹 | 사용 가능 |
3. ROLLUP — 계층적 부분합
ROLLUP(a, b, c) 은 GROUP BY (a, b, c), (a, b), (a), () 의 모든 소계를 포함한 결과를 돌려줍니다.
SELECT dept_id, job, SUM(salary)
FROM emp
GROUP BY ROLLUP(dept_id, job);
결과에는 (dept_id, job), (dept_id) 소계, 전체 총계 행이 포함됩니다.
4. CUBE — 모든 조합의 부분합
CUBE(a, b) 는 ROLLUP보다 더 많은 조합을 생성. (a,b), (a), (b), () 모두.
SELECT dept_id, job, SUM(salary)
FROM emp
GROUP BY CUBE(dept_id, job);
5. GROUPING SETS — 지정한 조합만
SELECT dept_id, job, SUM(salary)
FROM emp
GROUP BY GROUPING SETS ((dept_id), (job), ());
원하는 조합만 골라 집계할 수 있어 ROLLUP·CUBE보다 유연.
6. GROUPING / GROUPING_ID 함수
소계 행과 상세 행을 구분할 때 사용.
SELECT
CASE WHEN GROUPING(dept_id) = 1 THEN '합계' ELSE TO_CHAR(dept_id) END AS dept,
SUM(salary)
FROM emp
GROUP BY ROLLUP(dept_id);
GROUPING(col)= 해당 컬럼이 소계 행에서 집계된 경우 1, 아니면 0.GROUPING_ID(a, b, c)= 여러 컬럼의 GROUPING 결과를 비트마스크로 합산.
7. NULL과 GROUP BY
GROUP BY는 NULL을 하나의 그룹으로 처리합니다.
SELECT dept_id, COUNT(*) FROM emp GROUP BY dept_id;
-- dept_id가 NULL인 행도 하나의 그룹으로 집계
8. 자주 출제되는 포인트
ROLLUPvsCUBEvsGROUPING SETS의 조합 수 차이.WHERE는 집계 전,HAVING은 집계 후.GROUPING함수로 소계 행을 라벨링.GROUP BY에서 NULL은 하나의 그룹.
9. 요약 체크리스트
- GROUP BY와 HAVING의 차이를 표로 설명할 수 있다.
- ROLLUP/CUBE/GROUPING SETS 각각의 조합을 생성할 수 있다.
- GROUPING 함수로 소계 행을 구분할 수 있다.
- 집계 결과에서 NULL 그룹이 발생하는 이유를 안다.