SQLD 2과목에서 윈도우 함수는 문법 자체보다 “동점이 있을 때 결과가 어떻게 달라지는가”를 묻는 경우가 많습니다. RANK와 DENSE_RANK의 차이, 누적 합계의 기본 윈도우 범위 같은 부분에서 점수가 갈립니다.
이번 글에서는 순위 함수, 누적 집계, LAG·LEAD, NTILE, NULL 처리까지 8문제를 풀어봅니다. 모든 문제는 아래 하나의 표를 기준으로 하고, 결과는 실제로 쿼리를 실행해 검산했습니다.
이 글의 구성
- 문제 1~2: RANK·DENSE_RANK·ROW_NUMBER 비교, 부서별 1위 뽑기
- 문제 3~4: 누적 합계와 윈도우 범위(ROWS, RANGE)
- 문제 5~6: LAG·LEAD, NTILE
- 문제 7~8: 이동 평균, NULL과 집계 함수
공통 테이블 (아래 모든 문제에서 사용)
EMP NAME DEPT SAL A 10 300 B 10 300 C 10 200 D 20 500 E 20 400 F 20 400 G 20 100 H 30 250
문제 1. RANK와 DENSE_RANK의 차이
EMP 전체를 SAL 내림차순으로 정렬했을 때, 다음 쿼리에서 사원 A의 RK1, RK2 값은 각각 얼마인가?
SELECT NAME, SAL,
RANK() OVER (ORDER BY SAL DESC) RK1,
DENSE_RANK() OVER (ORDER BY SAL DESC) RK2
FROM EMP;
정답: RK1 = 4, RK2 = 3
SAL 내림차순은 500(D), 400(E, F), 300(A, B), 250(H), 200(C), 100(G) 순서입니다. RANK는 동점자 수만큼 다음 순위를 건너뛰므로 500이 1위, 400 두 명이 공동 2위, 그다음 300은 4위가 됩니다. DENSE_RANK는 건너뛰지 않아 300이 3위입니다. ROW_NUMBER는 동점이어도 항상 고유한 번호를 매기지만, 동점자 사이의 순서는 보장되지 않는다는 점도 함께 기억해 두세요.
문제 2. 부서별 최고 급여자 조회
부서별로 급여가 가장 높은 사원을 조회하려고 한다. 아래 쿼리의 결과 행 수는 몇 건인가?
SELECT NAME, DEPT, SAL
FROM (SELECT NAME, DEPT, SAL,
RANK() OVER (PARTITION BY DEPT ORDER BY SAL DESC) RK
FROM EMP)
WHERE RK = 1;
정답: 4건 (A, B, D, H)
PARTITION BY로 부서마다 따로 순위를 매깁니다. 10번 부서는 A와 B가 300으로 동점이라 둘 다 1위이고, 20번은 D, 30번은 H가 1위입니다. 동점을 허용하는 RANK를 썼기 때문에 부서 수(3)보다 많은 4건이 나옵니다. 부서당 정확히 1건만 원하면 ROW_NUMBER를 써야 합니다. 또한 윈도우 함수는 WHERE절에 직접 쓸 수 없어서 위처럼 인라인 뷰로 감싸 바깥에서 RK를 걸러냅니다.
문제 3. ORDER BY만 쓴 누적 합계
20번 부서만 대상으로 할 때, 사원 F의 누적 합계 S는 얼마인가?
SELECT NAME, SAL,
SUM(SAL) OVER (ORDER BY SAL) S
FROM EMP
WHERE DEPT = 20;
정답: 900
윈도우 절을 생략하고 ORDER BY만 쓰면 기본 범위는 RANGE UNBOUNDED PRECEDING ~ CURRENT ROW입니다. RANGE는 정렬 값이 같은 행을 모두 현재 행으로 취급하기 때문에, SAL이 400인 E와 F는 둘 다 100+400+400 = 900이 됩니다. 결과는 G 100, E 900, F 900, D 1400입니다. 행이 하나씩 누적될 거라 생각하고 500을 고르는 것이 대표적인 오답입니다.
문제 4. ROWS 범위를 지정한 누적 합계
문제 3의 쿼리를 아래처럼 바꾸면 사원 F의 S는 얼마인가?
SUM(SAL) OVER (ORDER BY SAL
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) S
정답: 900 (E는 500)
ROWS는 값이 아니라 물리적인 행 위치를 기준으로 합니다. 정렬된 순서가 G, E, F, D이면 누적값은 100, 500, 900, 1400입니다. 문제 3과 비교하면 F는 같지만 E가 900에서 500으로 달라집니다. 동점 행을 어떻게 처리하느냐가 RANGE와 ROWS의 핵심 차이이고, ROWS에서 동점자 간의 순서는 ORDER BY에 기준을 더 주지 않으면 불안정할 수 있습니다.
문제 5. LAG와 LEAD의 기본값
EMP에서 DEPT가 10 또는 30인 행(A, B, C, H)만 대상으로 할 때, 사원 A의 P와 사원 H의 N은 각각 무엇인가?
SELECT NAME, SAL,
LAG(SAL, 1, 0) OVER (ORDER BY NAME) P,
LEAD(SAL) OVER (ORDER BY NAME) N
FROM EMP
WHERE DEPT IN (10, 30);
정답: A의 P = 0, H의 N = NULL
LAG(컬럼, 오프셋, 기본값)은 앞쪽 행의 값을 가져오고, 앞 행이 없으면 세 번째 인자인 기본값(0)을 돌려줍니다. A는 첫 행이라 P가 0입니다. LEAD는 뒤쪽 행의 값을 가져오는데 기본값을 생략하면 NULL이 반환됩니다. H는 마지막 행이므로 N은 NULL입니다. 참고로 이 두 함수는 Oracle, SQL Server 등 주요 DBMS에서 모두 지원합니다.
문제 6. NTILE로 균등 분할
EMP 전체 8행을 NAME 순으로 NTILE(3)에 적용하면 사원 G가 속하는 그룹 번호와, 그룹별 행 수는?
정답: G는 3번 그룹, 그룹별 행 수는 3 / 3 / 2
NTILE(n)은 행을 n개 그룹으로 나누되, 나누어떨어지지 않으면 앞쪽 그룹에 행을 하나씩 더 배정합니다. 8행을 3개로 나누면 3, 3, 2건이 되고, A~C가 1번, D~F가 2번, G~H가 3번 그룹입니다. 몫과 나머지를 이용해 앞쪽 그룹이 더 커진다는 규칙을 기억하면 됩니다.
문제 7. 이동 평균 윈도우
20번 부서(D, E, F, G)에서 아래 쿼리를 실행할 때 사원 F의 이동 평균은 얼마인가?
SELECT NAME,
AVG(SAL) OVER (ORDER BY NAME
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) M
FROM EMP
WHERE DEPT = 20;
정답: 300
윈도우는 현재 행을 기준으로 앞 1행, 뒤 1행을 포함한 최대 3행입니다. F의 앞은 E(400), 뒤는 G(100)이므로 (400+400+100)/3 = 300입니다. 첫 행 D는 앞 행이 없어 D와 E만으로 (500+400)/2 = 450이 되고, 끝 행 G도 마찬가지로 행이 부족한 만큼만 계산에 들어갑니다. 경계 행에서 분모가 줄어든다는 점이 자주 출제됩니다.
문제 8. NULL과 집계 함수
테이블 T의 컬럼 A에 10, NULL, 20, NULL 네 행이 있다. 아래 쿼리의 결과 네 값을 각각 쓰시오.
SELECT COUNT(*), COUNT(A), SUM(A), AVG(A) FROM T;
정답: 4, 2, 30, 15
COUNT(*)는 NULL 여부와 관계없이 모든 행을 세므로 4입니다. COUNT(A)는 NULL이 아닌 값만 세어 2, SUM은 NULL을 제외하고 더해 30입니다. AVG도 NULL 행을 분모에서 빼므로 30/2 = 15이지, 30/4 = 7.5가 아닙니다. NULL을 0으로 보고 평균을 내고 싶다면 AVG(NVL(A, 0))처럼 NULL 처리 함수를 먼저 적용해야 합니다. NVL은 Oracle 함수이고 SQL Server에서는 ISNULL, 표준 SQL에서는 COALESCE를 씁니다.
공부 팁 3가지
- 동점이 있는 데이터를 직접 만들어 RANK, DENSE_RANK, ROW_NUMBER 결과를 손으로 먼저 적어본 뒤 실행해서 비교해 보세요. 눈으로 읽을 때보다 훨씬 오래 기억에 남습니다.
- 윈도우 절을 생략했을 때의 기본 범위(RANGE UNBOUNDED PRECEDING ~ CURRENT ROW)와 ROWS 지정 시의 차이를 한 줄로 외워 두면 누적 합계 문제를 안정적으로 풀 수 있습니다.
- NULL이 끼면 집계 함수, 비교 연산, 정렬 결과가 모두 달라집니다. 풀이 연습 때 NULL 행을 일부러 하나씩 섞어 두는 습관을 들이세요.
안내
이 글의 문제는 학습을 위해 직접 만든 예상문제이며 실제 시험과 다를 수 있습니다. 최신 출제 범위와 시험 일정은 한국데이터산업진흥원 등 공식 공지를 반드시 확인하세요. DBMS마다 함수와 기본 동작이 조금씩 다를 수 있으니 시험에 쓰이는 Oracle 기준으로도 점검하시기 바랍니다.