SQL

[SQL] TOP N QUERY

beginner-in-coding 2025. 2. 26. 12:04

01. TOP N QUERY

  • 페이징 처리를 효과적으로 수행하기 위해 사용
  • 전체 결과에서 특정 N개 추출
    • 예: 성적 상위자 3명

02. TOP-N 행 추출 방법

  1. ROWNUM
  2. RANK
  3. FETCH
  4. TOP N(SQL Server)

03. ROWNUM

  • 출력된 데이터 기준으로 행 번호 부여
  • 절대적인 행 번호가 아닌 가상의 번호 → 특정 행을 지정할 수 없음(= 연산 불가)
  • 첫 번째 행이 증가한 이후 할당 → '>' 연산자 사용 불가(0 은 가능)
SELECT ROWNUM, emp.*
FROM emp
WHERE sal >= 1500;  --ROWNUM을 출력 형태

* 잘못된 사용

SELECT *
FROM emp
WHERE ROWNUM > 1;  --잘못된 사용, 크기 조건 전달 불가
SELECT *
FROM emp
WHERE ROWNUM = 4;  --잘못된 사용2, 항상 불변하는 절대적인 번호가 아니므로 '='연산자는 단독 전달 불가

* 올바른 사용

SELECT empno, ename, deptno, sal
FROM emp
WHERE ROWNUM <= 5;  --올바른 사용 방법
  • EQUAL 비교 시 작다(<)와 함께 사용 → 1번부터 순서대로 뽑을 수 있음, 출력 가능함
  • 정렬 순서에 따라 출력되는 ROWNUM이 달라짐

** 잘못된 예 1: emp 테이블에서 급여가 높은 순서대로 상위 5명의 직원 정보 출력 **

SELECT empno, ename, deptno, sal
FROM emp
WHERE ROWNUM <= 5
ORDER BY sal DESC;
  • WHERE 절에 의해 먼저 5개를 추출 뒤 이 결과 집합에 대해 정렬 수행
  • 해결 방법: 먼저 서브쿼리를 사용(인라인뷰)하여 sal에 대해 내림차순 정렬을 한 후 상위 5개를 추출
SELECT *
FROM (SELECT *  --서브쿼리로 정렬 먼저 수행
	FROM emp
	ORDER BY sal DESC)
WHERE ROWNUM <= 5  --정렬된 컬럼에서 상위 5 추출
ORDER BY sal DESC;
  • ROWNUM이 결정되기 전에 먼저 데이터 정렬 순서를 바꿔놓는 방법

** 잘못된 예 2: 테이블에서 급여가 높은 순서대로 4~6번 째 해당하는 직원 정보 출력 **

SELECT *
FROM (SELECT *
	FROM emp
    ORDER BY sal DESC)
WHERE ROWNUM BETWEEN 4 AND 6
ORDER BY sal DESC;
  • ROWNUM 시작 값(1)이 정의되지 않았으므로 1을 건너뛰고 그 다음 행 번호에 대한 추출 불가
  • 해결 1 : 인라인 뷰에서 각 행마다 순위를 직접 부여
SELECT *
FROM (SELECT ROWNUM AS rn, A.*  --각 행마다 순위를 직접 부여
	FROM emp
    ORDER BY sal DESC) A) B  --순위가 추가된 테이블로
WHERE rn BETWEEN 4 AND 6  --순위가 4 ~ 6 사이
ORDER BY sal DESC;

* 서브쿼리를 통해 얻은 결과에 ROWNUM을 다시 부여하여 새로운 테이블인 것처럼 사용

  • 해결 2: 윈도우 함수의 RANK 사용
SELECT *
FROM (SELECT emp.*
	RANK() OVER(ORDER BY sal DESC) AS rn  --RANK 사용
    FROM emp) A
WHERE rn BETWEEN 4 AND 6
ORDER BY sal DESC;

04. FETCH 절

  • 출력될 행의 수를 제한하는 절
  • ORACLE 12C이상부터 제공 (이전 버전: ROWNUM 사용)
  • ORDER BY절 뒤에 사용(내부 파싱 순서도 ORDER BY 뒤)
  • 문법
SELECT 
FROM
WHERE
GROUP BY
HAVING
ORDER BY
OFFSET N { ROW | ROWS }
FETCH { FIRST | NEXT } N { ROW | ROWS } ONLY;
  • OFFSET: 건너뛸 행의 수
  • N: 출력할 행의 수
  • FETCH: 출력할 행의 수를 전달하는 구문
  • FIRST: (OFFSET을 사용하지 않았을 경우) 처음부터 N행 출력 명령
  • NEXT: (OFFSET을 사용했을 경우) 제외한 행 다음부터 N행 출력 명령
  • ROW | ROWS: 행의 수에 따라 하나일 경우 단수 | 여러 값이면 복수형(구분하지 않아도 가능)
  • 예제
SELECT empno, ename, job, sal
FROM emp
ORDER BY sal DESC 
FETCH  --출력할 행의 수를 전달하는 구문
FIRST  --OFFSET 없음 -> 처음부터 출력
5  --N: 출력할 행의 수
ROWS  --행의 수가 여러개: ROWS
ONLY;  --emp에서 sal 순서대로 상위 5명
SELECT empno, ename, job, sal
FROM emp
ORDER BY sal DESC
OFFSET 3 ROW  --OFFSET 사용: N(3)만큼 건너 뜀
FETCH  --출력할 행의 수를 전달
FIRST  --3 다음부터, 4부터 출력
2  --N: 2개
ROW ONLY;  --emp 테이블에서 급여가 높은 순서대로 4~5번째 해당하는 직원 정보 출력

05. TOP N 쿼리

  • SQL Sever에서 상위 N개 행 추출 문법
  • 서브쿼리 사용 없이 하나의 쿼리로 정렬된 순서대로 상위 N개 추출 가능
  • WITH TIES: 동순위까지 함께 출력 가능
  • 문법
SELECT TOP N 컬럼1, 컬럼2
FROM 테이블명
ORDER BY 정렬컬럼명 [ASC | DESC];
  • 예시
SELECT TOP 2 ename, sal
FROM emp
ORDER BY sal DESC;  --emp 테이블의 상위 급여자 2명 출력(SQL Server)
SELECT TOP 2 WITH TIES ename, sal
FROM emp
ORDER BY sal DESC;  --동순위 행도 함께 출력
  • TOP은 동순위여도 개수(N)를 기준으로 출력, WITH TIES를 이용하면 동순위 행 모두를 출력할 수 있음 

'SQL' 카테고리의 다른 글

[SQL] 윈도우 함수 (Window Function)  (0) 2025.02.26
[SQL] 그룹 함수  (0) 2025.02.17
[SQL] 집합 연산자  (0) 2025.02.17
[SQL] 서브쿼리  (0) 2025.02.17
[SQL] JOIN (2)  (0) 2025.02.17