developer life/database

[mssql] 페이징(paging) 쿼리 OFFSET ROWS FETCH NEXT 과 ROW_NUMBER() OVER()

노는개발자V 2023. 5. 26. 14:49

DECLARE @PAGE_NO INT = 0 -- 페이지 번호
DECLARE @PAGE_SIZE INT = 10 -- 한 페이지에 보여줄 row 수

페이징 쿼리를  만들 때 필요한 건 현재 페이지 번호와 한 화면에 출력될 페이지수가 필요하다.

페이지번호는 뷰단에서 사용자가 누른 페이지번호를 받아서 처리한다.

1. OFFSET ROWS FETCH NEXT(2012 버전부터 사용 가능)

SELECT t1.* 
		FROM 테이블명 AS t1 WITH(NOLOCK)  
		INNER JOIN ( 
			SELECT id 
			FROM 테이블명 WITH(NOLOCK)
			ORDER BY reg_date  DESC
			OFFSET (@PAGE_NO) * @PAGE_SIZE ROWS
			FETCH NEXT (@PAGE_SIZE)  ROWS ONLY 
		) AS t2
		ON t1.id = t2.id ORDER BY reg_date  DESC;

order by로 정렬기준을 정하고 offset을 통해 현재페이지수에 따른 계산으로  몇 개의 행을 가져올지를 정한다.

offset는 건너뛰기를 의미하며 fetch는 몇개의 행을 가져올지를 결정한다.

현재페이지가 0일경우 0개를 건너뛰고 10개를 가져오고 (0~ 10)

1일 경우 10개를 건너뛰고 10개를 가져오는 셈(10~20)이다.

 

장점으로는 빠르고 간편한 편이지만 단점으로는 top이나 over 등의 특정구문을 사용할 수 없다.

2. ROW_NUMBER() OVER()

SELECT *
FROM
(
	SELECT ROW_NUMBER() OVER(ORDER BY reg_date desc) AS rownum
		,* FROM 테이블명 lc 
) A
WHERE rownum BETWEEN ((@PAGE_NO)*@PAGE_SIZE)+1 AND ((@PAGE_NO+1)*@PAGE_SIZE)

row_number 함수로 조회된 결과물에 순차적 번호를 달아주고 rownum으로 내가 사용할 부분만 가져온다.

장점은 모든 게시물에 번호를 달아주기 때문에 특정 범위의 검색을 할수 있지만 단점으로는 부하를 일으킬 수 있고 속도가 느린 편이다.