본문으로 건너뛰기

그룹 함수: ROLLUP·CUBE

정보처리기사 목차SQL 기본레슨 93 / 233

목차

그룹 함수 ROLLUP·CUBE·GROUPING SETS는 GROUP BY 결과에 소계와 총계 줄을 더합니다. GROUPING 함수는 어느 줄이 합계를 낸 줄인지 1과 0으로 알려 줍니다.

학과·학년마다 학생 수를 세다 보면 학과별 소계와 전체 총계도 함께 보고 싶어집니다. 그룹과 집계: GROUP BY·HAVING의 GROUP BY 하나로는 학과·학년마다의 줄만 나옵니다. 그룹 함수를 쓰면 GROUP BY 절 하나로 소계와 총계를 함께 냅니다. 실기 출제기준도 그룹 함수로 소계·중계·총합계를 내는 DML을 적어 둡니다. 자료에 따라 COUNT·SUM 같은 집계 함수까지 묶어 그룹 함수라고 부르기도 합니다. 이 레슨에서는 ROLLUP·CUBE·GROUPING SETS를 가리킵니다.

5단계 중 1단계. GROUP BY 학과코드, 학년은 학과와 학년이 같은 학생끼리 한 줄로 셉니다.

그림은 학과코드가 NULL인 강도현(107)을 뺀 학생 6행으로 세다가, 마지막에 강도현을 넣습니다.

1ROLLUP — 소계와 총계 줄

GROUP BY 학과코드, 학년은 학과와 학년이 같은 학생끼리 한 줄로 셉니다. CS-2 2명, CS-3 1명, EE-1 1명, EE-3 2명, 4줄입니다. GROUP BY ROLLUP(학과코드, 학년)⁠으로 바꾸면 학과마다 소계 줄이 끼어들고, 맨 끝에 총계 줄이 붙습니다. CS 3명, EE 3명, 총계 6명으로 7줄입니다. 소계 줄에서 묶지 않은 열(학년)은 NULL로 보입니다.

2CUBE와 GROUPING SETS — 어떤 묶음을 낼까

CUBE(학과코드, 학년)는 학년별 소계까지 더합니다. 1학년 1명, 2학년 2명, 3학년 3명 세 줄이 더해져 10줄입니다. GROUPING SETS(학과코드, 학년)⁠는 괄호 안에 적은 묶음, 곧 학과별 소계와 학년별 소계만 냅니다. 상세 줄과 총계 줄이 없어 5줄입니다. ROLLUP은 오른쪽 열부터 하나씩 빼며 묶음을 만들고, CUBE는 가능한 모든 조합을 만듭니다. ()는 아무 열로도 묶지 않은 총계입니다.

그룹 함수열 둘(A, B)일 때 묶음열이 n개일 때 묶음 수
ROLLUP(A, B) · (A) · ()n + 1
CUBE(A, B) · (A) · (B) · ()2ⁿ
GROUPING SETS괄호 안에 적은 것만적은 수
  • 묶음 수는 결과 행 수가 아닙니다. 위 ROLLUP은 묶음이 3가지이고 결과는 7행입니다.
  • ROLLUP은 열 순서를 바꾸면 소계가 달라집니다. CUBE는 열 순서를 바꿔도 같은 묶음이 나옵니다.

3GROUPING — 데이터의 NULL과 합계 줄의 NULL

강도현까지 넣으면 학과코드가 NULL인 줄이 데이터의 NULL인지 합계 줄의 NULL인지 겉으로 가릴 수 없습니다. GROUPING(학과코드)는 합계를 내느라 학과코드를 비운 줄에서 1, 나머지 줄에서 0을 돌려줍니다.

예제

결과 표는 Oracle에서 돌린 결과입니다. Oracle은 오름차순 정렬에서 NULL을 맨 뒤에 두므로, ORDER BY 학과코드, 학년이면 학과마다 소계 줄이 그 학과 줄들 바로 아래에 옵니다.

ROLLUP

SELECT 학과코드,
  학년,
  COUNT(*) AS 인원
FROM 학생
WHERE 학과코드 IS NOT NULL
GROUP BY ROLLUP(학과코드, 학년)
ORDER BY 학과코드, 학년;
학과코드학년인원
CS22
CS31
CSNULL3
EE11
EE32
EENULL3
NULLNULL6

(CS, NULL)은 CS 학과의 소계, (NULL, NULL)은 총계입니다.

CUBE

SELECT 학과코드,
  학년,
  COUNT(*) AS 인원
FROM 학생
WHERE 학과코드 IS NOT NULL
GROUP BY CUBE(학과코드, 학년)
ORDER BY 학과코드, 학년;
학과코드학년인원
CS22
CS31
CSNULL3
EE11
EE32
EENULL3
NULL11
NULL22
NULL33
NULLNULL6

ROLLUP 결과에 학년별 소계 세 줄이 더해졌습니다. (NULL, 3) 3명은 CS 3학년 1명과 EE 3학년 2명의 합입니다.

GROUPING SETS

SELECT 학과코드,
  학년,
  COUNT(*) AS 인원
FROM 학생
WHERE 학과코드 IS NOT NULL
GROUP BY GROUPING SETS(
    학과코드, 학년)
ORDER BY 학과코드, 학년;
학과코드학년인원
CSNULL3
EENULL3
NULL11
NULL22
NULL33

학과별로 센 결과와 학년별로 센 결과를 위아래로 이어 붙인 것과 같습니다.

107까지 넣으면 — GROUPING

WHERE를 빼면 학과코드가 NULL인 강도현이 들어옵니다. ORDER BY 학과코드, 학년만으로는 (NULL, NULL)인 두 줄의 차례가 정해지지 않아, GROUPING으로 먼저 정렬합니다.

SELECT 학과코드,
  학년,
  COUNT(*) AS 인원,
  GROUPING(학과코드) AS G
FROM 학생
GROUP BY ROLLUP(학과코드, 학년)
ORDER BY GROUPING(학과코드),
  학과코드, 학년;
학과코드학년인원G
CS220
CS310
CSNULL30
EE110
EE320
EENULL30
NULL110
NULLNULL10
NULLNULL71
  • (NULL, 1) 1명은 학과가 없는 1학년 강도현의 줄입니다. 학과코드 NULL은 데이터의 NULL입니다.
  • (NULL, NULL)이 두 줄입니다. G가 0인 1명 줄은 학과가 NULL인 그룹의 소계이고, G가 1인 7명 줄이 총계입니다.
  • 이렇게 섞이지 않게 하려면 앞의 예제처럼 WHERE로 NULL인 행을 빼거나, GROUPING으로 가릅니다.

시험 포인트

  • 필기: ROLLUP은 n + 1가지, CUBE는 2ⁿ가지 묶음으로 합계를 냅니다. ROLLUP은 열 순서를 바꾸면 결과가 달라지고, CUBE는 같습니다. 소계·총계 줄에서 묶지 않은 열은 NULL로 보이며, 데이터의 NULL과는 GROUPING으로 가립니다.
  • 실기: 그룹 함수를 쓴 쿼리의 결과를 소계·총계 줄까지 행 차례대로 씁니다. 설명을 보고 ROLLUP·CUBE·GROUPING SETS·GROUPING을 가려 씁니다.

확인 문제

1. 수강 표를 GROUP BY CUBE(과목코드, 학번)⁠으로 묶습니다. 합계를 내는 묶음으로 알맞은 것을 고르세요.

  • ① (과목코드, 학번) · (과목코드)
  • ② (과목코드, 학번) · (과목코드) · ()
  • ③ (과목코드, 학번) · (과목코드) · (학번)
  • ④ (과목코드, 학번) · (과목코드) · (학번) · ()
정답

④입니다. CUBE는 적은 열로 만들 수 있는 모든 조합으로 묶습니다. 열이 둘이면 2²이라 네 가지이고, 아무 열로도 묶지 않은 총계 ()도 그 가운데 하나입니다.

  • ① ROLLUP의 묶음에서 총계까지 뺀 꼴입니다. 묶음은 ROLLUP도 n + 1가지라 셋입니다.
  • ② ROLLUP(과목코드, 학번)의 묶음입니다. 오른쪽 열부터 하나씩 빼므로 학번만으로 묶은 소계가 없습니다.
  • ③ 총계를 빼먹었습니다. 2ⁿ의 n에는 열 수를 넣고, 그 가운데 하나가 총계입니다.

2. 수강 표를 과목코드와 학번으로 묶어 점수 합계를 냅니다. (가)~(라)에 맞는 함수의 이름을 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

  • (가) 과목코드별 소계와 맨 끝의 총계는 내고, 학번별 소계는 내지 않습니다.
  • (나) (가)의 결과에 학번별 소계까지 더해 냅니다.
  • (다) 과목코드별 소계와 학번별 소계만 내고, 상세 줄과 총계 줄은 내지 않습니다.
  • (라) 결과에 보이는 NULL이 데이터에 있던 값인지, 소계를 내며 비워진 칸인지 숫자로 알려 줍니다.
정답

받는 답: (가) ROLLUP · (나) CUBE · (다) GROUPING SETS · (라) GROUPING

(가)는 왼쪽 열부터 차례로만 소계를 내고, (나)는 모든 조합으로 냅니다. (다)는 괄호 안에 적은 묶음만 내 상세 줄과 총계 줄이 없습니다. (라)는 줄을 만들지 않고 가려 주기만 합니다.

  • 틀리는 꼴 (다)에 GROUPING: 이름이 비슷하지만 줄을 만드는 쪽은 GROUPING SETS입니다. SETS까지 적어야 받습니다.
  • 틀리는 꼴 (나)에 ROLLUP(학번, 과목코드): 열 순서를 바꿔도 소계가 생기는 열이 하나뿐입니다. 둘 다 내려면 CUBE입니다.
  • 틀리는 꼴 (라)에 GROUP BY: 묶으라고 알려 주는 절이지 함수가 아닙니다.

3. 수강 표의 점수 합계를 냅니다. (1)~(3)을 차례로 풀어 보세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.

(1) 아래 쿼리의 결과 표에서 (가)·(나)를 채우세요.

과목코드합계
DS320
NW(가)
OS210
NULL(나)
SELECT 과목코드,
  SUM(점수) AS 합계
FROM 수강
GROUP BY ROLLUP(과목코드)
ORDER BY 과목코드;

(2) 같은 쿼리의 ROLLUP만 CUBE로 바꾸면 결과는 몇 행일까요?

(3) 70점 이상인 점수만 보고 과목코드별 합계와 전체 총계를 내는 쿼리를 쓰고, 결과를 쓰세요.

정답

받는 답: (1) (가) 370 · (나) 900 · (2) 4행 · (3) 아래 둘째 블록

(1) NW는 80 + 55 + 95 + 90 + 50 = 370이고, NULL 줄은 12행을 모두 더한 총계 900입니다. (2) 열이 하나면 CUBE의 묶음도 (과목코드)와 () 둘이라 ROLLUP과 같은 4행입니다. 2ⁿ의 n이 1이라 2가지입니다.

과목코드합계
DS320
NW370
OS210
NULL900

(3)은 WHERE로 행을 먼저 거르고 남은 행만 더합니다.

SELECT 과목코드,
  SUM(점수) AS 합계
FROM 수강
WHERE 점수 >= 70
GROUP BY ROLLUP(과목코드)
ORDER BY 과목코드;
과목코드합계
DS255
NW265
OS150
NULL670
  • 틀리는 꼴 (2) 8행: 2ⁿ의 n에 데이터의 과목 수 3을 넣었습니다. n은 묶으려고 적은 열 수입니다.
  • 틀리는 꼴 (2) 3행: CUBE가 총계 줄을 내지 않는다고 봤습니다. 열이 하나여도 총계 줄은 붙습니다.
  • 틀리는 꼴 (3) NULL 줄에 900: 총계 줄도 WHERE를 거친 행만 더합니다. 걸러진 60·65·55·50은 들어가지 않습니다.

더 자세히: SQLD의 그룹 함수

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

정보처리기사 목차로