Search
moon
sun

21.Top-N 쿼리 · PIVOT

•
ROWNUM 이 무엇인지 알고, 정렬 전에 부여되는 특성과 함정을 설명할 수 있다.
•
Top-N 쿼리를 인라인 뷰로 정확히 작성할 수 있다.
•
PIVOT / UNPIVOT 으로 행과 열을 서로 바꿀 수 있다.

1부. Top-N 쿼리

1. ROWNUM 이란 ⭐⭐

1) 조회 결과에 자동으로 붙는 가상 컬럼

•
ROWNUM: SELECT 결과의 각 행에 1부터 순서대로 매겨지는 번호
•
테이블에 실제 존재하는 컬럼이 아니라, 조회할 때마다 생성되는 가상 컬럼(pseudo column)
-- ============================================================ -- 【이해용 예제】 ROWNUM 은 결과 행에 자동으로 붙는다 -- ============================================================ SELECT ROWNUM, ENAME, SAL FROM EMP; -- ROWNUM ENAME SAL -- ------ ------ ----- -- 1 SMITH 800 ← 결과의 첫 번째 행 -- 2 ALLEN 1600 ← 두 번째 행 -- 3 WARD 1250 -- ... -- 14 MILLER 1300 -- -- ⭐ ROWNUM 은 '조회 결과가 만들어지는 순서' 대로 매겨진다. -- 테이블에 저장된 값이 아니라 조회할 때마다 새로 붙는다.
SQL
복사

2) 가상 컬럼 두 가지 — ROWNUM vs ROWID ⭐

가상 컬럼
의미
특징
ROWNUM
조회 결과의 순번
1부터, 조회마다 바뀜
ROWID
행의 물리적 저장 주소
고유·불변 (행의 실제 위치)
SELECT ROWNUM, ROWID, ENAME FROM EMP WHERE ROWNUM <= 2; -- ROWNUM ROWID ENAME -- ------ ------------------ ------ -- 1 AAAR3sAAEAAAACEAAA SMITH ← ROWID 는 저장 주소 (18자리) -- 2 AAAR3sAAEAAAACEAAB ALLEN -- -- ⭐ ROWNUM 은 '몇 번째로 조회됐나', ROWID 는 '어디에 저장돼 있나'. -- ROWID 로 조회하면 가장 빠르게 그 행을 찾는다 (물리 주소이므로).
SQL
복사

2. ROWNUM 의 함정 ⭐⭐⭐

🔥 이 단원 최다 출제입니다. ROWNUM 은 정렬(ORDER BY)보다 먼저 매겨집니다.

1) 왜 함정이 생기는가 — 실행 순서

-- ============================================================ -- 【시험용 예제】 ROWNUM 은 정렬 전에 매겨진다 ★★★ -- ============================================================ -- ❌ "급여 높은 3명" 을 이렇게 쓰면 틀린다! SELECT ROWNUM, ENAME, SAL FROM EMP WHERE ROWNUM <= 3 ORDER BY SAL DESC; -- ROWNUM ENAME SAL -- ------ ------ ----- -- 1 SMITH 800 ⚠️ 급여가 높은 3명이 아니다! -- 2 ALLEN 1600 -- 3 WARD 1250 -- → WHERE ROWNUM<=3 이 '먼저' 실행되어 아무 3명(SMITH,ALLEN,WARD)이 뽑히고, -- 그 3명을 ORDER BY 로 정렬만 한 것. 전체에서 정렬한 게 아니다!
SQL
복사

2) ROWNUM = N 과 ROWNUM > N 은 항상 빈 결과 ⭐⭐

-- ============================================================ -- 【시험용 예제】 ROWNUM 비교의 함정 ★★★ -- ============================================================ -- ✅ ROWNUM <= N : 정상 (1,2,...,N 선택) SELECT ENAME FROM EMP WHERE ROWNUM <= 3; -- 3건 ✅ -- ❌ ROWNUM = N (N>1) : 결과 없음! SELECT ENAME FROM EMP WHERE ROWNUM = 2; -- → 0건 ⚠️ -- 이유: ROWNUM 은 '조건을 통과한 행' 에게 1부터 붙는다. -- 첫 행이 ROWNUM=1 인데 'ROWNUM=2' 를 만족 못 해 탈락 → 다음 행도 ROWNUM=1 시도 -- → 영원히 2에 도달 못 함 → 0건 -- ❌ ROWNUM > 1 : 결과 없음! SELECT ENAME FROM EMP WHERE ROWNUM > 1; -- → 0건 ⚠️ (첫 행이 ROWNUM=1 이라 '>1' 이 거짓 → 통과 못 함 → 계속 반복) -- ⭐ 정리 -- ROWNUM <= N → ✅ 동작 -- ROWNUM < N → ✅ 동작 -- ROWNUM = 1 → ✅ 동작 (유일하게 = 이 되는 값) -- ROWNUM = N(≥2)→ ❌ 항상 0건 -- ROWNUM > N → ❌ 항상 0건
SQL
복사

3. Top-N 쿼리 ⭐⭐

1) Top-N 쿼리란

정렬된 결과에서 상위(또는 하위) N개만 뽑아내는 조회
•
Top-N: "Top(상위) N개" — 순위가 높은 몇 건만 골라내는 것
•
실무에서 매우 흔한 요구입니다.
실무 요구 예
Top-N
"급여 상위 5명"
급여 내림차순 상위 5
"최근 주문 10건"
주문일 내림차순 상위 10
"판매량 하위 3개 상품"
판매량 오름차순 상위 3
"성적 1등"
성적 내림차순 상위 1
💡 핵심은 "정렬(ORDER BY) → 자르기(상위 N)" 두 단계입니다. 그런데 2절에서 봤듯 ROWNUM 은 정렬보다 먼저 매겨지므로, 이 순서를 맞추는 게 관건입니다.

2) 인라인 뷰로 "정렬 먼저, ROWNUM 나중"

-- ============================================================ -- 【시험용 예제】 급여 높은 상위 3명 — 올바른 방법 ★★ -- ============================================================ SELECT ROWNUM AS 순위, ENAME, SAL FROM ( SELECT ENAME, SAL FROM EMP ORDER BY SAL DESC ) -- ① 인라인 뷰 안에서 '먼저' 정렬 WHERE ROWNUM <= 3; -- ② 정렬된 결과에 ROWNUM 을 매겨 상위 3개 -- 순위 ENAME SAL -- ---- ------ ----- -- 1 KING 5000 -- 2 SCOTT 3000 -- 3 FORD 3000 -- -- ⭐ 핵심: 인라인 뷰에서 정렬을 끝낸 뒤, 바깥에서 ROWNUM 으로 자른다. -- 정렬된 순서대로 ROWNUM 이 매겨지므로 진짜 Top-N 이 나온다.
SQL
복사

3) RANK 와의 차이

-- 공동 순위를 어떻게 처리하느냐가 다르다 -- ROWNUM 방식 : 3위에서 딱 끊음 (SCOTT, FORD 중 하나만 나올 수도) -- RANK 방식 : 공동 순위를 모두 포함 SELECT ENAME, SAL, RANK() OVER (ORDER BY SAL DESC) AS RK FROM EMP WHERE ... ; -- RANK 는 인라인뷰로 감싸 RK <= 3 (20강) -- 3000 공동 2위(SCOTT,FORD)가 모두 나오고 그다음이 4위
SQL
복사
방식
공동 순위
ROWNUM <= N
정확히 N건 (공동순위 잘림 가능)
RANK() <= N
공동순위 모두 포함 (N건 초과 가능)

2부. PIVOT / UNPIVOT

5. PIVOT — 행을 열로 ⭐⭐

1) 세로 데이터를 가로 교차표로

-- ============================================================ -- 【시험용 예제】 부서별·직무별 급여합계를 교차표로 ★★ -- ============================================================ SELECT * FROM ( SELECT DEPTNO, JOB, SAL FROM EMP ) -- 원본 (필요한 컬럼만) PIVOT ( SUM(SAL) -- ① 집계함수 (필수!) FOR JOB IN ('CLERK' AS 사원, -- ② 어떤 값을 '컬럼' 으로 펼칠지 'MANAGER' AS 관리자, 'ANALYST' AS 분석가) ); -- DEPTNO 사원 관리자 분석가 -- ------ ----- ------ ------ -- 10 1300 2450 (NULL) -- 20 1900 2975 6000 -- 30 950 2850 (NULL) -- -- ⭐ 원본에서 'JOB' 컬럼의 값(CLERK,MANAGER,ANALYST)들이 '컬럼명' 으로 눕는다. -- 각 교차 지점은 SUM(SAL) 로 집계된다.
SQL
복사
PIVOT 요소
역할
집계함수
교차 지점을 어떻게 집계할지 (필수)
FOR 컬럼
어떤 컬럼의 값을 열로 펼칠지
IN (값들)
열로 만들 값을 직접 나열 (동적 불가)
⚠️ PIVOT은 열로 만들 값을 IN 절에 직접 써야 합니다. "모든 직무를 자동으로"는 안 됩니다.

2) UNPIVOT — 열을 행으로 (역방향)

-- 가로로 펼쳐진 컬럼들을 다시 세로 행으로 되돌린다 -- 예: (사원, 관리자, 분석가) 3개 컬럼 → JOB 이라는 1개 컬럼의 값들로 SELECT * FROM 교차표 UNPIVOT ( SAL FOR JOB IN (사원, 관리자, 분석가) ); -- → PIVOT 의 반대. 컬럼명이 행의 값이 된다. -- ⚠️ UNPIVOT 은 NULL 인 칸을 기본적으로 제외한다.
SQL
복사

6. 출제 포인트 한눈에 정리

#
꼭 외울 것
핵심
1
ROWNUM
조회 결과 순번 (가상 컬럼, 1부터)
2
ROWID
행의 물리적 저장 주소 (고유·불변)
3
ROWNUM 부여 시점
정렬(ORDER BY) 전 ⭐
4
ROWNUM = N(N≥2)
항상 0건 ⭐⭐
5
ROWNUM > N
항상 0건 ⭐
6
ROWNUM <= N
정상 동작
7
Top-N 정석
인라인뷰로 정렬 먼저, ROWNUM 나중 ⭐
8
PIVOT
행→열, 집계함수 필수 ⭐
9
PIVOT IN 절
열로 만들 값 직접 나열
10
UNPIVOT
열→행 (역방향)

9. 확인 문제

Q1. ROWNUM 과 ROWID 의 차이는?
정답 보기
Q2. 다음 SQL이 "급여 높은 3명"을 제대로 조회하지 못하는 이유는?
SELECT ENAME, SAL FROM EMP WHERE ROWNUM <= 3 ORDER BY SAL DESC;
SQL
복사
정답 보기
Q3. WHERE ROWNUM = 2 의 결과가 0건인 이유는?
정답 보기
Q4. ROWNUM <= 3, ROWNUM = 1, ROWNUM = 3, ROWNUM > 1 중 결과가 나오는 것은?
정답 보기
Q5. PIVOT 을 사용할 때 반드시 필요한 것은?
정답 보기
Q6. UNPIVOT 은 무엇을 하는가?
정답 보기