1. 개념 비교: 두 함수의 근본적인 차이
항목 |
ROWNUM |
ROW_NUMBER() |
순번 부여 시점 |
SELECT 이후, ORDER BY 이전 |
ORDER BY 이후에 윈도우 함수로 번호 부여 |
정렬 반영 여부 |
반영되지 않음 |
원하는 정렬 기준 반영 가능 |
고유성 |
보장되지 않음 |
고유하게 1부터 순번 부여 |
페이징 용이성 |
서브쿼리 필요 |
직관적이고 쉬움 |
사용 가능 DB |
Oracle 한정 |
SQL 표준을 지원하는 대부분의 DB |
2. ROWNUM: 정렬 전 순번 부여의 한계
잘못된 ROWNUM 사용 예
SELECT employee_id, name, salary
FROM employees
WHERE ROWNUM <= 3
ORDER BY salary DESC;
문제점: ROWNUM은 정렬 이전에 순번이 부여되므로, 원하는 정렬 기준이 반영되지 않은 채 임의의 3명이 추출됨
잘못된 결과 예시 (ROWNUM은 정렬 전에 적용됨)
employee_id |
name |
salary |
105 |
Alice |
3200 |
107 |
Brian |
2900 |
102 |
Charlie |
2700 |
해결 방법: 서브쿼리를 활용한 올바른 사용
SELECT *
FROM (
SELECT * FROM employees ORDER BY salary DESC
)
WHERE ROWNUM <= 3;
3. ROW_NUMBER(): 정렬 반영 + 정확한 순번
정렬 기준에 따라 정확히 순번 부여
SELECT *
FROM (
SELECT employee_id, name, salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn
FROM employees
) t
WHERE rn <= 3;
정확한 결과 예시 (ROW_NUMBER 기준)
employee_id |
name |
salary |
rn |
120 |
Kevin |
9100 |
1 |
121 |
Sarah |
8900 |
2 |
122 |
Jane |
8700 |
3 |
4. 실전 적용 예시
간단한 상위 N개 추출 (정렬 불필요 시)
SELECT * FROM employees WHERE ROWNUM <= 10;
페이징 처리 (예: 페이지 2, 11~20위)
SELECT *
FROM (
SELECT employee_id, name, salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn
FROM employees
) t
WHERE rn BETWEEN 11 AND 20;
부서별 급여 1위 추출
SELECT *
FROM (
SELECT employee_id, department_id, salary,
ROW_NUMBER() OVER (PARTITION BY department_id ORDER BY salary DESC) AS rn
FROM employees
) t
WHERE rn = 1;
5. 요약: 언제 어떤 함수를 써야 할까?
상황 |
추천 함수 |
이유 |
단순 N개 추출 (정렬 무관) |
ROWNUM |
간단한 조건으로 빠르게 처리 가능 |
정확한 Top N, 페이징 |
ROW_NUMBER() |
정렬 기준 반영 및 정확한 순번 제공 가능 |
그룹 내 순위 필요 |
ROW_NUMBER() |
PARTITION으로 그룹별 순번 부여 가능 |
다양한 DB 지원 필요 |
ROW_NUMBER() |
SQL 표준 기반으로 여러 DB에서 호환 가능 |