•
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 은 무엇을 하는가?
정답 보기





