ANSI/ISO SQL 표준은 데이터 분석을 위해 세 가지 주요 함수를 정의하고 있다
Aggregate Function은 주어진 데이터 집합에 대해 계산을 수행하여 단일 값을 반환하는 함수입니다. 주요 집계 함수는 다음과 같다.
이 함수들은 GROUP BY 절과 함께 사용되어 데이터 그룹별로 요약된 정보를 제공할 수 있다.
Group Function은 그룹별로 데이터를 집계하여 다양한 레벨의 결산 보고서를 만들 때 유용한다. 주요 그룹 함수는 다음과 같다.
이 함수들은 GROUP BY 절의 확장 형태로, 데이터를 한 번만 읽어서 빠르게 리포트를 생성할 수 있도록 돕는다. 또한, GROUPING 함수와 CASE 함수를 이용하여 다양한 형식의 보고서를 작성할 수 있다.
Window Function은 분석 함수(Analytic Function) 또는 순위 함수(Rank Function)로도 불리며, 데이터웨어하우스 환경에서 발전한 기능입니다. 이 함수들은 데이터의 특정 집합(window) 내에서 계산을 수행한다. 주요 윈도우 함수는 다음과 같다.
이 함수들은 데이터 집합 내에서 여러 행에 걸쳐 계산을 수행할 수 있어 복잡한 분석 작업에 유용하다. 예를 들어, 이동 평균, 누적 합계 등을 계산할 때 사용된다.
ROLLUP 함수는 데이터의 다차원 집계를 쉽게 계산하기 위한 SQL의 기능 중 하나이다. GROUP BY 절과 함께 사용되며, 주어진 그룹 컬럼 리스트에 대해 소계를 포함한 여러 레벨의 집계 결과를 생성한다. ROLLUP 함수는 N개의 그룹 컬럼에 대해 N+1 레벨의 소계를 생성합니다. 이는 데이터의 계층 구조를 반영하기 때문에 인수의 순서가 중요하다.
부서명(DNAME)과 업무명(JOB) 기준으로 사원 수와 급여 합계를 집계한다.
SELECT DNAME, JOB, COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY DNAME, JOB;
| DNAME | JOB | Total Empl | Total Sal |
|---|---|---|---|
| SALES | MANAGER | 1 | 2850 |
| SALES | CLERK | 1 | 950 |
| ACCOUNTING | MANAGER | 1 | 2450 |
| RESEARCH | ANALYST | 2 | 6000 |
| ACCOUNTING | CLERK | 1 | 1300 |
| SALES | SALESMAN | 4 | 5600 |
| RESEARCH | MANAGER | 1 | 2975 |
| ACCOUNTING | PRESIDENT | 1 | 5000 |
| RESEARCH | CLERK | 2 | 1900 |
정렬된 결과를 얻기 위해 ORDER BY 절을 추가한다.
SELECT DNAME, JOB, COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY DNAME, JOB
ORDER BY DNAME, JOB;
ROLLUP 함수를 사용하여 소계와 총계를 계산한다.
ROLLUP(DNAME, JOB)는 다음과 같은 계층 구조로 소계를 계산한다.
SELECT DNAME, JOB, COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY ROLLUP (DNAME, JOB);
| DNAME | JOB | Total Empl | Total Sal |
|---|---|---|---|
| SALES | CLERK | 1 | 950 |
| SALES | MANAGER | 1 | 2850 |
| SALES | SALESMAN | 4 | 5600 |
| SALES | 6 | 9400 | |
| RESEARCH | CLERK | 2 | 1900 |
| RESEARCH | ANALYST | 2 | 6000 |
| RESEARCH | MANAGER | 1 | 2975 |
| RESEARCH | 5 | 10875 | |
| ACCOUNTING | CLERK | 1 | 1300 |
| ACCOUNTING | MANAGER | 1 | 2450 |
| ACCOUNTING | PRESIDENT | 1 | 5000 |
| ACCOUNTING | 3 | 8750 | |
| 14 | 29025 |
DNAME(SALES, RESEARCH, ACCOUNTING)과 JOB(CLERK, MANAGER, SALESMAN) 의 ) JOB(CLERK, MANAGER, SALESMAN)DNAME과 JOB별 집계가 어떻게 되는지는, 다음과 같다.
ROLLUP과 ORDER BY를 함께 사용하여 정렬된 소계 결과를 얻는다.
SELECT DNAME, JOB, COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY ROLLUP (DNAME, JOB)
ORDER BY DNAME, JOB;
ROLLUP 함수의 결과를 구분하기 위해 GROUPING 함수를 사용한다.
SELECT DNAME, GROUPING(DNAME), JOB, GROUPING(JOB), COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY ROLLUP (DNAME, JOB);
| DNAME | DNAME_GROUPING | JOB | JOB_GROUPING | Total Empl | Total Sal |
|---|---|---|---|---|---|
| ACCOUNTING | 0 | CLERK | 0 | 1 | 1300 |
| ACCOUNTING | 0 | MANAGER | 0 | 1 | 2450 |
| ACCOUNTING | 0 | PRESIDENT | 0 | 1 | 5000 |
| ACCOUNTING | 0 | NULL | 1 | 3 | 8750 |
| RESEARCH | 0 | ANALYST | 0 | 2 | 6000 |
| RESEARCH | 0 | CLERK | 0 | 1 | 800 |
| RESEARCH | 0 | MANAGER | 0 | 1 | 2975 |
| RESEARCH | 0 | NULL | 1 | 4 | 9775 |
| SALES | 0 | CLERK | 0 | 1 | 950 |
| SALES | 0 | MANAGER | 0 | 1 | 2850 |
| SALES | 0 | SALESMAN | 0 | 4 | 5600 |
| SALES | 0 | NULL | 1 | 6 | 9400 |
| NULL | 1 | NULL | 1 | 13 | 28125 |
CASE 함수를 사용하여 집계 레코드에 원하는 텍스트를 표시한다.
SELECT CASE GROUPING(DNAME) WHEN 1 THEN 'All Departments' ELSE DNAME END AS DNAME,
CASE GROUPING(JOB) WHEN 1 THEN 'All Jobs' ELSE JOB END AS JOB,
COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY ROLLUP (DNAME, JOB);
Oracle DECODE 함수 사용 예는 다음과 같다.
SELECT DECODE(GROUPING(DNAME), 1, 'All Departments', DNAME) AS DNAME,
DECODE(GROUPING(JOB), 1, 'All Jobs', JOB) AS JOB,
COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY ROLLUP (DNAME, JOB);
GROUP BY 절의 일부 컬럼에만 ROLLUP을 적용한다.
SELECT CASE GROUPING(DNAME) WHEN 1 THEN 'All Departments' ELSE DNAME END AS DNAME,
CASE GROUPING(JOB) WHEN 1 THEN 'All Jobs' ELSE JOB END AS JOB,
COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY DNAME, ROLLUP(JOB);
결과는 다음과 같다.
| DNAME | JOB | Total Empl | Total Sal |
|---|---|---|---|
| SALES | CLERK | 1 | 950 |
| SALES | MANAGER | 1 | 2850 |
| SALES | SALESMAN | 4 | 5600 |
| SALES | 6 | 9400 | |
| RESEARCH | CLERK | 2 | 1900 |
| RESEARCH | ANALYST | 2 | 6000 |
| RESEARCH | MANAGER | 1 | 2975 |
| RESEARCH | 5 | 10875 | |
| ACCOUNTING | CLERK | 1 | 1300 |
| ACCOUNTING | MANAGER | 1 | 2450 |
| ACCOUNTING | PRESIDENT | 1 | 5000 |
| ACCOUNTING | 3 | 8750 |
일부만 ROLLUP을 사용하여,
All Departments,All Jobs가 나타나지 않는거다!!
하나의 집합으로 여러 컬럼을 그룹화하여 ROLLUP을 적용한다.
SELECT DNAME, JOB, MGR, SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY ROLLUP (DNAME, (JOB, MGR));
| DNAME | JOB | MGR | Total Sal |
|---|---|---|---|
| SALES | CLERK | 7698 | 950 |
| SALES | MANAGER | 7839 | 2850 |
| SALES | SALESMAN | 7698 | 5600 |
| SALES | 9400 | ||
| RESEARCH | CLERK | 7788 | 1100 |
| RESEARCH | CLERK | 7902 | 800 |
| RESEARCH | ANALYST | 7566 | 6000 |
| RESEARCH | MANAGER | 7839 | 2975 |
| RESEARCH | 10875 | ||
| ACCOUNTING | CLERK | 7782 | 1300 |
| ACCOUNTING | MANAGER | 7839 | 2450 |
| ACCOUNTING | PRESIDENT | 5000 | |
| ACCOUNTING | 8750 | ||
| 29025 |
ROLLUP함수는 그룹별 소계와 총계를 계산하는 데 유용하다.인수 순서는 결과에 영향을 미치므로 주의해야 한다.GROUPING함수는 집계 레코드를 구분하는 데 사용된다.CASE/DECODE함수와 함께 사용하면 집계 결과에 사용자 정의 텍스트를 추가할 수 있다.
이와 같이 ROLLUP 함수를 활용하면 복잡한 데이터 집계를 쉽게 수행하고, 다양한 레벨의 요약 정보를 효율적으로 얻을 수 있다.
CUBE 함수는 지정된 그룹 컬럼들에 대해 가능한 모든 조합의 다차원 집계를 생성하는 SQL 기능입니다. 이는 ROLLUP 함수보다 더 많은 조합을 다루며, 각 그룹 컬럼의 모든 가능한 값을 포함한 집계를 생성합니다. 이를 통해 복잡한 데이터 분석을 간단히 수행할 수 있지만, 시스템에 더 큰 부하를 주기 때문에 사용에 주의가 필요합니다.
ROLLUP 함수와 달리 CUBE 함수는 계층 구조가 없으며, 그룹 컬럼의 순서는 결과의 정렬에만 영향을 미친다.부서명(DNAME)과 업무명(JOB)을 기준으로 집계하고, CUBE 함수를 사용하여 모든 조합의 집계를 생성한다.
SELECT CASE GROUPING(DNAME) WHEN 1 THEN 'All Departments' ELSE DNAME END AS DNAME,
CASE GROUPING(JOB) WHEN 1 THEN 'All Jobs' ELSE JOB END AS JOB,
COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY CUBE (DNAME, JOB);
실행 결과는 다음과 같다.
| DNAME | JOB | Total Empl | Total Sal |
|---|---|---|---|
| All Departments | All Jobs | 14 | 29025 |
| All Departments | CLERK | 4 | 4150 |
| All Departments | ANALYST | 2 | 6000 |
| All Departments | MANAGER | 3 | 8275 |
| All Departments | SALESMAN | 4 | 5600 |
| All Departments | PRESIDENT | 1 | 5000 |
| SALES | All Jobs | 6 | 9400 |
| SALES | CLERK | 1 | 950 |
| SALES | MANAGER | 1 | 2850 |
| SALES | SALESMAN | 4 | 5600 |
| RESEARCH | All Jobs | 5 | 10875 |
| RESEARCH | CLERK | 2 | 1900 |
| RESEARCH | ANALYST | 2 | 6000 |
| RESEARCH | MANAGER | 1 | 2975 |
| ACCOUNTING | All Jobs | 3 | 8750 |
| ACCOUNTING | CLERK | 1 | 1300 |
| ACCOUNTING | MANAGER | 1 | 2450 |
| ACCOUNTING | PRESIDENT | 1 | 5000 |
All Departments와 All Jobs 조합의 총계를 포함한다.CUBE 함수의 결과를 여러 SQL 쿼리를 UNION ALL로 합쳐서 얻는 방법이다.
SELECT DNAME, JOB, COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY DNAME, JOB
UNION ALL
SELECT DNAME, 'All Jobs', COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY DNAME
UNION ALL
SELECT 'All Departments', JOB, COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY JOB
UNION ALL
SELECT 'All Departments', 'All Jobs', COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO;
결과는 다음과 같다.
- CUBE 함수는 그룹 컬럼의 모든 가능한 조합에 대해 소계를 생성하는 다차원 집계 함수이다.
- 사용 주의: 시스템 부하가 크므로 주의해서 사용해야 한다.
- 비교: ROLLUP 함수는 계층적 소계를 생성하며, CUBE 함수는 모든 조합에 대해 소계를 생성한다.
- 효율성: 여러 쿼리를 UNION ALL로 합치는 것보다 효율적이다.
이와 같이 CUBE 함수는 복잡한 데이터 분석 작업에서 매우 유용한 도구이다. 그러나 사용 시 시스템 성능에 주는 영향을 고려하여 신중하게 사용해야 한다.
GROUPING SETS 함수는 SQL에서 다양한 소계 집합을 쉽게 만들 수 있게 해주는 기능이다. 이를 통해 여러 번의 GROUP BY 쿼리를 반복하지 않고도 다양한 집계 결과를 한 번에 얻을 수 있다. GROUPING SETS에 지정된 인수들은 평등한 관계를 가지며, 인수의 순서가 바뀌어도 결과에는 영향이 없다. 결과에 대한 정렬이 필요할 경우, ORDER BY 절을 사용해야 한다.
GROUPING 함수는 SQL에서 ROLLUP, CUBE, GROUPING SETS와 같은 집계 함수와 함께 사용되어, 결과 집합에서 특정 행이 소계를 나타내는지 아니면 일반적인 집계 결과를 나타내는지를 구분할 수 있도록 한다.
ROLLUP, CUBE, GROUPING SETS와 함께 사용될 때 유용하다.부서별, 업무별 인원수와 급여 합을 구하는 쿼리이다.
SELECT DNAME, 'All Jobs' AS JOB, COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY DNAME
UNION ALL
SELECT 'All Departments' AS DNAME, JOB, COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY JOB;
| DNAME | JOB | Total Empl | Total Sal |
|---|---|---|---|
| ACCOUNTING | All Jobs | 3 | 8750 |
| RESEARCH | All Jobs | 5 | 10875 |
| SALES | All Jobs | 6 | 9400 |
| All Departments | CLERK | 4 | 4150 |
| All Departments | SALESMAN | 4 | 5600 |
| All Departments | PRESIDENT | 1 | 5000 |
| All Departments | MANAGER | 3 | 8275 |
| All Departments | ANALYST | 2 | 6000 |
GROUPING SETS를 이용하여 동일한 결과를 얻는 쿼리이다.
SELECT DECODE(GROUPING(DNAME), 1, 'All Departments', DNAME) AS DNAME,
DECODE(GROUPING(JOB), 1, 'All Jobs', JOB) AS JOB,
COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY GROUPING SETS (DNAME, JOB);
| DNAME | JOB | Total Empl | Total Sal |
|---|---|---|---|
| All Departments | CLERK | 4 | 4150 |
| All Departments | SALESMAN | 4 | 5600 |
| All Departments | PRESIDENT | 1 | 5000 |
| All Departments | MANAGER | 3 | 8275 |
| All Departments | ANALYST | 2 | 6000 |
| ACCOUNTING | All Jobs | 3 | 8750 |
| RESEARCH | All Jobs | 5 | 10875 |
| SALES | All Jobs | 6 | 9400 |
GROUPING SETS의 인수 순서를 변경하여 동일한 결과를 얻는 쿼리이다.
SELECT DECODE(GROUPING(DNAME), 1, 'All Departments', DNAME) AS DNAME,
DECODE(GROUPING(JOB), 1, 'All Jobs', JOB) AS JOB,
COUNT(*) AS "Total Empl", SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY GROUPING SETS (JOB, DNAME);
| DNAME | JOB | Total Empl | Total Sal |
|---|---|---|---|
| All Departments | CLERK | 4 | 4150 |
| All Departments | SALESMAN | 4 | 5600 |
| All Departments | PRESIDENT | 1 | 5000 |
| All Departments | MANAGER | 3 | 8275 |
| All Departments | ANALYST | 2 | 6000 |
| ACCOUNTING | All Jobs | 3 | 8750 |
| RESEARCH | All Jobs | 5 | 10875 |
| SALES | All Jobs | 6 | 9400 |
해당 쿼리문은 아래와 같이 동작한다.
먼저 GROUPING SETS (DNAME, JOB)는 다음과 같은 집계를 생성한다.
그 다음, GROUPING 함수를 보자.
GROUPING(DNAME)는 DNAME 컬럼이 소계를 나타내는 경우 1을 반환하고, 그렇지 않으면 0을 반환한다.DECODE(GROUPING(DNAME), 1, 'All Departments', DNAME)는 DNAME 컬럼이 소계를 나타내는 경우 'All Departments'를, 그렇지 않은 경우 실제 부서명을 반환한다.GROUPING(JOB)는 JOB 컬럼이 소계를 나타내는 경우 1을 반환하고, 그렇지 않으면 0을 반환한다.DECODE(GROUPING(JOB), 1, 'All Jobs', JOB)는 JOB 컬럼이 소계를 나타내는 경우 'All Jobs'를, 그렇지 않은 경우 실제 업무명을 반환한다부서, 업무, 매니저 별 집계와 그 조합별 집계를 구하는 쿼리이다.
SELECT DNAME, JOB, MGR, SUM(SAL) AS "Total Sal"
FROM EMP, DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
GROUP BY GROUPING SETS ((DNAME, JOB, MGR), (DNAME, JOB), (JOB, MGR));
| DNAME | JOB | MGR | Total Sal |
|---|---|---|---|
| SALES | CLERK | 7698 | 950 |
| ACCOUNTING | CLERK | 7782 | 1300 |
| RESEARCH | CLERK | 7788 | 1100 |
| RESEARCH | CLERK | 7902 | 800 |
| RESEARCH | ANALYST | 7566 | 6000 |
| SALES | MANAGER | 7839 | 2850 |
| RESEARCH | MANAGER | 7839 | 2975 |
| ACCOUNTING | MANAGER | 7839 | 2450 |
| SALES | SALESMAN | 7698 | 5600 |
| ACCOUNTING | PRESIDENT | NULL | 5000 |
| CLERK | NULL | 7698 | 950 |
| CLERK | NULL | 7782 | 1300 |
| CLERK | NULL | 7788 | 1100 |
| CLERK | NULL | 7902 | 800 |
| ANALYST | NULL | 7566 | 6000 |
| MANAGER | NULL | 7839 | 8275 |
| SALESMAN | NULL | 7698 | 5600 |
| PRESIDENT | NULL | NULL | 5000 |
| SALES | MANAGER | NULL | 2850 |
| SALES | CLERK | NULL | 950 |
| ACCOUNTING | CLERK | NULL | 1300 |
| ACCOUNTING | MANAGER | NULL | 2450 |
| ACCOUNTING | PRESIDENT | NULL | 5000 |
| RESEARCH | MANAGER | NULL | 2975 |
| SALES | SALESMAN | NULL | 5600 |
| RESEARCH | ANALYST | NULL | 6000 |
| RESEARCH | CLERK | NULL | 1900 |
- GROUPING SETS 함수는 지정된 여러 그룹 조합에 대해 각각 집계를 생성하는 기능이다.
- 인수의 순서는 결과에 영향을 미치지 않으며, 인수들은 평등한 관계를 가진다.
- 정렬: 결과를 정렬하려면 ORDER BY 절을 사용해야 한다.
- 효율성: 여러 번의 GROUP BY 쿼리를 반복하지 않고도 다양한 집계를 한 번에 수행할 수 있다.
GROUPING SETS 함수는 데이터 분석에서 다양한 집계 작업을 효율적으로 처리하는 데 매우 유용한 도구이다.
- GROUPING SETS: 다양한 소계 집합을 한 번에 만들 수 있는 SQL 기능이다.
- GROUPING 함수: 소계와 총계를 구분하는 데 사용되며, CASE 문과 함께 사용하여 결과를 명확하게 표시할 수 있다.
- 효율성: GROUPING SETS는 여러 번의 GROUP BY 쿼리를 반복하지 않고도 다양한 집계 결과를 한 번에 얻을 수 있다.
이와 같이 GROUPING SETS와 GROUPING 함수를 사용하면, SQL 쿼리를 간결하게 유지하고 복잡한 데이터 집계 작업을 효율적으로 수행할 수 있다.