SQL Server 2012부터는 OFFSET…FETCH
절을 이용한 페이징이 공식 지원되며, 가장 간단하고 효율적인 방식입니다. 기본 문법과 예시를 보시죠.
1. OFFSET … FETCH NEXT
문법
SELECT 컬럼들
FROM 테이블명
WHERE <조건>
ORDER BY 정렬칼럼 [ASC|DESC] -- ORDER BY 절 필수
OFFSET (@PageIndex - 1) * @PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY;
- @PageIndex: 요청하는 페이지 번호 (1부터 시작)
- @PageSize: 한 페이지 당 레코드 개수
OFFSET 0 ROWS
→ 첫 페이지, OFFSET 10 ROWS
→ 세 번째 페이지(@PageSize=5일 때)
예시
DECLARE @PageIndex INT = 2; -- 2페이지
DECLARE @PageSize INT = 10; -- 페이지당 10개
SELECT
UserId,
UserName,
CreatedDate
FROM dbo.Users
WHERE IsActive = 1
ORDER BY CreatedDate DESC
OFFSET (@PageIndex - 1) * @PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY;
- 위 쿼리는
CreatedDate
기준 내림차순으로 정렬한 뒤,
2페이지(11번째~20번째) 레코드를 반환합니다.
2. 총 레코드 수와 함께 페이징
페이징 API 구현 시에는 전체 레코드 수도 같이 제공하는 경우가 많습니다. 다음처럼 COUNT(*) OVER()
윈도우 함수를 함께 쓰면 한 번의 쿼리로 총 개수와 페이지 데이터를 동시에 가져올 수 있습니다.
DECLARE @PageIndex INT = 1,
@PageSize INT = 5;
SELECT
UserId,
UserName,
CreatedDate,
TotalCount = COUNT(1) OVER()
FROM dbo.Users
WHERE IsActive = 1
ORDER BY CreatedDate DESC
OFFSET (@PageIndex - 1) * @PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY;
- 결과에
TotalCount
컬럼이 추가되어, 별도 SELECT COUNT(*)
없이 전체 건수를 얻을 수 있습니다.
3. 레거시 방식 (SQL Server 2008 이하)
구버전에서는 ROW_NUMBER()
윈도우 함수를 이용해야 합니다. SQL Server 2012 이후에도 호환성을 위해 가끔 씁니다.
DECLARE @PageIndex INT = 3,
@PageSize INT = 20;
WITH OrderedUsers AS (
SELECT
UserId,
UserName,
CreatedDate,
RN = ROW_NUMBER() OVER (ORDER BY CreatedDate DESC)
FROM dbo.Users
WHERE IsActive = 1
)
SELECT
UserId,
UserName,
CreatedDate
FROM OrderedUsers
WHERE RN BETWEEN (@PageIndex - 1) * @PageSize + 1
AND @PageIndex * @PageSize
ORDER BY RN;
팁
ORDER BY
절 필수: 없으면 오류가 발생합니다.
- 인덱스 활용: 정렬 칼럼에 인덱스가 있어야 OFFSET/FETCH 성능이 좋습니다.
- 대량 건 페이징: 페이지가 깊어질수록(OFFSET 값이 커질수록) 속도가 느려지므로, 커서 기반 페이징(keyset pagination)도 고려하세요.
위 최신 문법(OFFSET…FETCH
)을 사용하시면 SQL Server에서 간편하게 페이징을 구현할 수 있습니다.