How to do pagination in SQL Server 2008

SqlSql Server-2008Pagination

Sql Problem Overview


How do you do pagination in SQL Server 2008 ?

Sql Solutions


Solution 1 - Sql

You can use ROW_NUMBER():

> Returns the sequential number of a row within a partition of a result set, starting at 1 for the first row in each partition.

Example:

WITH CTEResults AS
(
    SELECT IDColumn, SomeField, DateField, ROW_NUMBER() OVER (ORDER BY DateField) AS RowNum
    FROM MyTable
)

SELECT * 
FROM CTEResults
WHERE RowNum BETWEEN 10 AND 20;

Solution 2 - Sql

You can try something like

DECLARE @Table TABLE(
		Val VARCHAR(50)
)

DECLARE @PageSize INT,
		@Page INT
		
SELECT	@PageSize = 10,
		@Page = 2

;WITH PageNumbers AS(
		SELECT Val,
				ROW_NUMBER() OVER(ORDER BY Val) ID
		FROM	@Table
)
SELECT	*
FROM	PageNumbers
WHERE	ID	BETWEEN ((@Page - 1) * @PageSize + 1)
		AND	(@Page * @PageSize)

Solution 3 - Sql

SQL Server 2012 provides pagination functionality (see http://www.codeproject.com/Articles/442503/New-features-for-database-developers-in-SQL-Server)

In SQL2008 you can do it this way:

declare @rowsPerPage as bigint; 
declare @pageNum as bigint; 
set @rowsPerPage=25; 
set @pageNum=10;   

With SQLPaging As	( 
	Select Top(@rowsPerPage * @pageNum) ROW_NUMBER() OVER (ORDER BY ID asc) 
	as resultNum, * 
	FROM Employee )
select * from SQLPaging with (nolock) where resultNum > ((@pageNum - 1) * @rowsPerPage)

Prooven! It works and scales consistently.

Solution 4 - Sql

1) CREATE DUMMY DATA

CREATE TABLE #employee (EMPID INT IDENTITY, NAME VARCHAR(20))

DECLARE @id INT = 1

WHILE @id < 200

BEGIN
INSERT INTO #employee ( NAME ) VALUES ('employee_' + CAST(@id AS VARCHAR) )
SET @id = @id + 1
END

2) NOW APPLY THE SOLUTION.

This case assumes EMPID to be unique and sorted column.

Off-course, you will apply it a different column...

DECLARE @pageSize INT = 20

SELECT * FROM (
 
SELECT *, PageNumber =  CEILING(CAST(EMPID AS FLOAT)/@pageSize)   
FROM #employee
) MyQuery

WHERE MyQuery.PageNumber = 1		  

Solution 5 - Sql

These are my solution for paging the result of query in SQL server side. I have added the concept of filtering and order by with one column. It is very efficient when you are paging and filtering and ordering in your Gridview.

Before testing, you have to create one sample table and insert some row in this table : (In real world you have to change Where clause considering your table field and maybe you have some join and subquery in main part of select)

Create Table VLT
(
    ID int IDentity(1,1),
    Name nvarchar(50),
    Tel Varchar(20)
)
GO


Insert INTO VLT
VALUES
    ('NAME' + Convert(varchar(10),@@identity),'FAMIL' +     Convert(varchar(10),@@identity))
GO 500000

In SQL server 2008, you can use the CTE concept. Because of that, I have written two type of query for SQL server 2008+

-- SQL Server 2008+

DECLARE @PageNumber Int = 1200
DECLARE @PageSize INT = 200
DECLARE @SortByField int = 1 --The field used for sort by
DECLARE @SortOrder nvarchar(255) = 'ASC' --ASC or DESC
DECLARE @FilterType nvarchar(255) = 'None' --The filter type, as defined on the client side (None/Contain/NotContain/Match/NotMatch/True/False/)
DECLARE @FilterValue nvarchar(255) = '' --The value the user gave for the filter
DECLARE @FilterColumn int = 1 --The column to wich the filter is applied, represents the column number like when we send the information.

SELECT 
  Data.ID,
  Data.Name,
  Data.Tel
FROM
  (  
	SELECT 
	  ROW_NUMBER() 
		OVER( ORDER BY 
				CASE WHEN @SortByField = 1 AND @SortOrder = 'ASC'
					  THEN VLT.ID END ASC,
				CASE WHEN @SortByField = 1 AND @SortOrder = 'DESC'
					  THEN VLT.ID END DESC,
				CASE WHEN @SortByField = 2 AND @SortOrder = 'ASC'
					  THEN VLT.Name END ASC,
				CASE WHEN @SortByField = 2 AND @SortOrder = 'DESC'
					  THEN VLT.Name END ASC,
				CASE WHEN @SortByField = 3 AND @SortOrder = 'ASC'
					  THEN VLT.Tel END ASC,
				CASE WHEN @SortByField = 3 AND @SortOrder = 'DESC'
					  THEN VLT.Tel END ASC
		 ) AS RowNum
	  ,*  
	FROM VLT 
	WHERE
	  ( -- We apply the filter logic here
		CASE
		  WHEN @FilterType = 'None' THEN 1
      
		  -- Name column filter
		  WHEN @FilterType = 'Contain' AND @FilterColumn = 1
			AND ( -- In this case, when the filter value is empty, we want to show everything.
				VLT.ID LIKE '%' + @FilterValue + '%'
			   OR
				@FilterValue = ''
			   ) THEN 1
		  WHEN @FilterType = 'NotContain' AND @FilterColumn = 1
			AND ( -- In this case, when the filter value is empty, we want to show everything.
				VLT.ID NOT LIKE '%' + @FilterValue + '%'
			   OR
				@FilterValue = ''
			   ) THEN 1
		  WHEN @FilterType = 'Match' AND @FilterColumn = 1
			AND VLT.ID = @FilterValue THEN 1
		  WHEN @FilterType = 'NotMatch' AND @FilterColumn = 1
			AND VLT.ID <> @FilterValue THEN 1               
      
		  -- Name column filter
		  WHEN @FilterType = 'Contain' AND @FilterColumn = 2
			AND ( -- In this case, when the filter value is empty, we want to show everything.
				VLT.Name LIKE '%' + @FilterValue + '%'
			   OR
				@FilterValue = ''
			   ) THEN 1
		  WHEN @FilterType = 'NotContain' AND @FilterColumn = 2
			AND ( -- In this case, when the filter value is empty, we want to show everything.
				VLT.Name NOT LIKE '%' + @FilterValue + '%'
			   OR
				@FilterValue = ''
			   ) THEN 1
		  WHEN @FilterType = 'Match' AND @FilterColumn = 2
			AND VLT.Name = @FilterValue THEN 1
		  WHEN @FilterType = 'NotMatch' AND @FilterColumn = 2
			AND VLT.Name <> @FilterValue THEN 1         
        
		 -- Tel column filter   
		 WHEN @FilterType = 'Contain' AND @FilterColumn = 3
			AND ( -- In this case, when the filter value is empty, we want to show everything.
				VLT.Tel LIKE '%' + @FilterValue + '%'
			   OR
				@FilterValue = ''
			   ) THEN 1
		  WHEN @FilterType = 'NotContain' AND @FilterColumn = 3
			AND ( -- In this case, when the filter value is empty, we want to show everything.
				VLT.Tel NOT LIKE '%' + @FilterValue + '%'
			   OR
				@FilterValue = ''
			   ) THEN 1
		  WHEN @FilterType = 'Match' AND @FilterColumn = 3
			AND VLT.Tel = @FilterValue THEN 1
		  WHEN @FilterType = 'NotMatch' AND @FilterColumn = 3
			AND VLT.Tel <> @FilterValue THEN 1    
        
		END
	  ) = 1   
  ) AS Data
WHERE Data.RowNum > @PageSize * (@PageNumber - 1)
  AND Data.RowNum <= @PageSize * @PageNumber
ORDER BY Data.RowNum

GO

And second solution with CTE in SQL server 2008+

DECLARE @PageNumber Int = 1200
DECLARE @PageSize INT = 200
DECLARE @SortByField int = 1 --The field used for sort by
DECLARE @SortOrder nvarchar(255) = 'ASC' --ASC or DESC
DECLARE @FilterType nvarchar(255) = 'None' --The filter type, as defined on the client side (None/Contain/NotContain/Match/NotMatch/True/False/)
DECLARE @FilterValue nvarchar(255) = '' --The value the user gave for the filter
DECLARE @FilterColumn int = 1 --The column to wich the filter is applied, represents the column number like when we send the information.

;WITH
  Data_CTE
  AS
  (  
	SELECT 
	  ROW_NUMBER() 
		OVER( ORDER BY 
				CASE WHEN @SortByField = 1 AND @SortOrder = 'ASC'
					  THEN VLT.ID END ASC,
				CASE WHEN @SortByField = 1 AND @SortOrder = 'DESC'
					  THEN VLT.ID END DESC,
				CASE WHEN @SortByField = 2 AND @SortOrder = 'ASC'
					  THEN VLT.Name END ASC,
				CASE WHEN @SortByField = 2 AND @SortOrder = 'DESC'
					  THEN VLT.Name END ASC,
				CASE WHEN @SortByField = 3 AND @SortOrder = 'ASC'
					  THEN VLT.Tel END ASC,
				CASE WHEN @SortByField = 3 AND @SortOrder = 'DESC'
					  THEN VLT.Tel END ASC
		 ) AS RowNum
	  ,*  
	FROM VLT
	WHERE
	  ( -- We apply the filter logic here
		CASE
		  WHEN @FilterType = 'None' THEN 1
      
		  -- Name column filter
		  WHEN @FilterType = 'Contain' AND @FilterColumn = 1
			AND ( -- In this case, when the filter value is empty, we want to show everything.
				VLT.ID LIKE '%' + @FilterValue + '%'
			   OR
				@FilterValue = ''
			   ) THEN 1
		  WHEN @FilterType = 'NotContain' AND @FilterColumn = 1
			AND ( -- In this case, when the filter value is empty, we want to show everything.
				VLT.ID NOT LIKE '%' + @FilterValue + '%'
			   OR
				@FilterValue = ''
			   ) THEN 1
		  WHEN @FilterType = 'Match' AND @FilterColumn = 1
			AND VLT.ID = @FilterValue THEN 1
		  WHEN @FilterType = 'NotMatch' AND @FilterColumn = 1
			AND VLT.ID <> @FilterValue THEN 1               
      
		  -- Name column filter
		  WHEN @FilterType = 'Contain' AND @FilterColumn = 2
			AND ( -- In this case, when the filter value is empty, we want to show everything.
				VLT.Name LIKE '%' + @FilterValue + '%'
			   OR
				@FilterValue = ''
			   ) THEN 1
		  WHEN @FilterType = 'NotContain' AND @FilterColumn = 2
			AND ( -- In this case, when the filter value is empty, we want to show everything.
				VLT.Name NOT LIKE '%' + @FilterValue + '%'
			   OR
				@FilterValue = ''
			   ) THEN 1
		  WHEN @FilterType = 'Match' AND @FilterColumn = 2
			AND VLT.Name = @FilterValue THEN 1
		  WHEN @FilterType = 'NotMatch' AND @FilterColumn = 2
			AND VLT.Name <> @FilterValue THEN 1         
        
		 -- Tel column filter   
		 WHEN @FilterType = 'Contain' AND @FilterColumn = 3
			AND ( -- In this case, when the filter value is empty, we want to show everything.
				VLT.Tel LIKE '%' + @FilterValue + '%'
			   OR
				@FilterValue = ''
			   ) THEN 1
		  WHEN @FilterType = 'NotContain' AND @FilterColumn = 3
			AND ( -- In this case, when the filter value is empty, we want to show everything.
				VLT.Tel NOT LIKE '%' + @FilterValue + '%'
			   OR
				@FilterValue = ''
			   ) THEN 1
		  WHEN @FilterType = 'Match' AND @FilterColumn = 3
			AND VLT.Tel = @FilterValue THEN 1
		  WHEN @FilterType = 'NotMatch' AND @FilterColumn = 3
			AND VLT.Tel <> @FilterValue THEN 1    
        
		END
	  ) = 1     
  )

SELECT 
  Data.ID,
  Data.Name,
  Data.Tel
FROM Data_CTE AS Data
WHERE Data.RowNum > @PageSize * (@PageNumber - 1)
  AND Data.RowNum <= @PageSize * @PageNumber
ORDER BY Data.RowNum

Solution 6 - Sql

Another solution which works from SQL 2005 at least, is to use TOP with SELECT subqueries and ORDER BY clauses.

In brief, retrieving page 2 rows with 10 rows per page is the same as retrieving the last 10 rows of the first 20 rows. Which translates into retrieving the first 20 rows with ASC order, and then the first 10 rows with DESC order, before ordering again using ASC.

Example : Retrieving page 2 rows with 3 rows per page

create table test(id integer);
insert into test values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);

select * 
    from (
        select top 2 * 
            from (
                select  top (4) * 
                    from test 
                    order by id asc) tmp1
            order by id desc) tmp1 
    order by id asc

Solution 7 - Sql

The query that i have used for pagination is this (on Oracle DB).

SELECT * FROM tableName
WHERE  RowNum >= 1
AND RowNum < 20
ORDER BY RowNum;

RowNum- it is variable provide by DB .For each row returned by a query, the ROWNUM pseudocolumn returns a number indicating the order in which Oracle selects the row from a table or set of joined rows.

Solution 8 - Sql

SELECT DISTINCT Id,ParticipantId,ActivityDate,IsApproved,
	IsDeclined,IsDeleted,SubmissionDate,	IsResubmitted,	
	
	[CategoryId] Id,[CategoryName] Name,
	
	[ActivityId] [Id],[ActivityName] Name,Points,	
	
	[UserId] [Id],Email,
	ROW_NUMBER() OVER(ORDER BY Id desc)   AS RowNum from
	(SELECT DISTINCT
	Id,ParticipantId,
	ActivityDate,IsApproved,
	IsDeclined,IsDeleted,
	SubmissionDate,	IsResubmitted,	
	
	[CategoryId] [CategoryId],[CategoryName] [CategoryName],
	
	[ActivityId] [ActivityId],[ActivityName] [ActivityName],Points,	
	
	[UserId] [UserId],Email,
	ROW_NUMBER() OVER(ORDER BY Id desc)   AS RowNum from
	
	 (SELECT DISTINCT ASN.Id,
	ASN.ParticipantId,ASN.ActivityDate,
	ASN.IsApproved,ASN.IsDeclined,
	ASN.IsDeleted,ASN.SubmissionDate,
	CASE WHEN (SELECT COUNT(*) FROM FDS_ActivitySubmission WHERE ParentId=ASN.Id)>0 THEN CONVERT(BIT, 1) ELSE CONVERT(BIT, 0) END IsResubmitted,
	
	AC.Id [CategoryId],	AC.Name [CategoryName],
	
	A.Id [ActivityId],A.Name [ActivityName],A.Points,
	
	U.Id[UserId],U.Email	
	
	
FROM
FDS_ActivitySubmission ASN WITH (NOLOCK)
INNER JOIN	
	FDS_ActivityCategory AC WITH (NOLOCK)
ON 
	AC.Id=ASN.ActivityCategoryId
		INNER JOIN
	FDS_ApproverDetails FDSA
ON
FDSA.ParticipantID=ASN.ParticipantID

		INNER JOIN
	   FDS_ActivityJobRole FAJ
ON
     FAJ.RoleId=FDSA.JobRoleId
	INNER JOIN

	FDS_Activity A WITH (NOLOCK)
ON 
	A.Id=ASN.ActivityId
INNER JOIN
   Users U WITH (NOLOCK)
ON
    ASN.ParticipantId=FDSA.ParticipantID
WHERE
       IsDeclined=@IsDeclined AND IsApproved=@IsApproved 	AND ASN.IsDeleted=0
       AND
       ISNULL(U.Id,0)=ISNULL(@ApproverId,0)
       AND ISNULL(ASN.IsDeleted,0)<>1)P)t where t.RowNum between 
	   (((@PageNumber - 1) * @PageSize) + 1) AND (@PageNumber * PageSize)
	AND t.IsDeclined=@IsDeclined AND t.IsApproved=@IsApproved AND t.IsDeleted = 0
 AND (ISNULL(t.Id,0)=ISNULL(@SubmissionId,0)or ISNULL(@SubmissionId,0)<=0) 
      

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionOmuView Question on Stackoverflow
Solution 1 - SqlAdaTheDevView Answer on Stackoverflow
Solution 2 - SqlAdriaan StanderView Answer on Stackoverflow
Solution 3 - SqlMarceBozuView Answer on Stackoverflow
Solution 4 - SqlRehmanAfridiView Answer on Stackoverflow
Solution 5 - SqlArdalan ShahgholiView Answer on Stackoverflow
Solution 6 - SqlNicolas RioussetView Answer on Stackoverflow
Solution 7 - Sqlmariq vlahovaView Answer on Stackoverflow
Solution 8 - Sqluser7488677View Answer on Stackoverflow