다차원 집계
GROUP BY의 확장인 ROLLUP, CUBE, GROUPING SETS로 소계와 총계를 한 번에 구하는 방법과, 소계 행의 NULL을 구분하는 GROUPING 함수
#핵심 요약
GROUP BY ROLLUP(a)는 a별 집계 아래에 전체 집계 한 행을 붙임
컬럼이 n개면 묶음은 n+1가지임
GROUP BY CUBE(a, b)는 가능한 모든 조합(2의 n제곱)으로 묶음
GROUP BY GROUPING SETS((a), (b), ())는 원하는 묶음만 지정함()는 전체 집계임
소계, 총계 행에서 "전체"를 뜻하는 NULL과 원래 데이터의 NULL은 GROUPING 함수로 구분함
전체를 뜻하면 1, 아니면 0임
#개념과 동작 원리
| 확장 | 묶음 | 3개 컬럼일 때 |
|---|---|---|
ROLLUP(a, b, c) |
앞에서부터 n개, n-1개,..., 0개 | (a,b,c), (a,b), (a), () 4가지 |
CUBE(a, b, c) |
모든 조합 | 8가지 |
GROUPING SETS(...) |
지정한 묶음만 | 지정한 수 |
첫 n개 식으로 묶인 행을 일반 행, 나머지를 소계(superaggregate) 행이라 함
ROLLUP에 SUM을 쓰면 가장 상세한 단계부터 총계까지 소계를 만듦
GROUPING SETS는 지정한 묶음만 계산하므로 CUBE나 ROLLUP의 전체 계산이 필요 없음
각 묶음 결과를 UNION ALL로 합치므로 중복 행이 나올 수 있음
괄호로 묶은 컬럼은 하나의 단위(복합 컬럼)로 계산됨
여러 GROUPING SETS, ROLLUP, CUBE를 쉼표로 나열하면 각 묶음의 곱이 됨
실습에서는 ROLLUP의 묶음 수를 "N + 1개"로 메모했음
예제4(ROLLUP(deptno, job, mgr)의 묶음 수)의 답은 공식 문서 규칙으로 4가지임
#필수 명령어 또는 SQL
#ROLLUP
SELECT job, SUM(sal)
FROM emp
GROUP BY ROLLUP(job);
SELECT deptno, job, SUM(sal)
FROM emp
GROUP BY ROLLUP(deptno, job);결과 해석: 두 번째 문장은 부서, 직업별 합계, 부서별 소계, 전체 합계를 한 결과로 냄
예제3은 중간마다 부서별 합계, 맨 아래 전체 합계를 요구함
실습에서는 같은 결과를 UNION ALL로 만든 문장보다 ROLLUP이 읽는 버퍼가 적다고 설명했음(집합 연산)
#CUBE
SELECT job, SUM(sal)
FROM emp
GROUP BY CUBE(job);
SELECT TO_CHAR(hiredate, 'YYYY'), job, SUM(sal)
FROM emp
GROUP BY CUBE(TO_CHAR(hiredate, 'YYYY'), job);결과 해석: 두 번째 문장은 연습 문제1의 요구(연도별 직업별, 연도별, 직업별, 전체 합계)를 CUBE 하나로 냄
연습 문제의 정답은 기재 없음
#GROUPING SETS
SELECT deptno, job, SUM(sal)
FROM emp
GROUP BY GROUPING SETS((deptno), (job), ())
ORDER BY job, deptno;
SELECT deptno, SUM(sal)
FROM emp
GROUP BY GROUPING SETS((deptno), ());결과 해석: 첫 문장은 부서별 합계, 직업별 합계, 전체 합계만 냄
두 번째 문장은 ROLLUP(deptno)와 같은 묶음임
#GROUPING으로 소계 행 구분
설명: SELECT에서 GROUPING을 쓰면 NULL로 보이던 소계 자리에 1이 나옴
SELECT deptno, job, SUM(sal), GROUPING(deptno), GROUPING(job)
FROM emp
GROUP BY ROLLUP(deptno, job);결과 해석:
DECODE(GROUPING(job), 1, '부서 소계', job)처럼 써서 소계 행에 이름을 붙일 수 있음