Equivalent of LIMIT and OFFSET for SQL Server?

SqlSql ServerPaginationLimitOffset

Sql Problem Overview


In PostgreSQL there is the Limit and Offset keywords which will allow very easy pagination of result sets.

What is the equivalent syntax for SQL Server?

Sql Solutions


Solution 1 - Sql

This feature is now made easy in SQL Server 2012. This is working from SQL Server 2012 onwards.

Limit with offset to select 11 to 20 rows in SQL Server:

SELECT email FROM emailTable 
WHERE user_id=3
ORDER BY Id
OFFSET 10 ROWS
FETCH NEXT 10 ROWS ONLY;
  • ORDER BY: required
  • OFFSET: optional number of skipped rows
  • NEXT: required number of next rows

Reference: https://docs.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql

Solution 2 - Sql

The equivalent of LIMIT is SET ROWCOUNT, but if you want generic pagination it's better to write a query like this:

;WITH Results_CTE AS
(
    SELECT
        Col1, Col2, ...,
        ROW_NUMBER() OVER (ORDER BY SortCol1, SortCol2, ...) AS RowNum
    FROM Table
    WHERE <whatever>
)
SELECT *
FROM Results_CTE
WHERE RowNum >= @Offset
AND RowNum < @Offset + @Limit

The advantage here is the parameterization of the offset and limit in case you decide to change your paging options (or allow the user to do so).

Note: the @Offset parameter should use one-based indexing for this rather than the normal zero-based indexing.

Solution 3 - Sql

select top {LIMIT HERE} * from (
      select *, ROW_NUMBER() over (order by {ORDER FIELD}) as r_n_n 
      from {YOUR TABLES} where {OTHER OPTIONAL FILTERS}
) xx where r_n_n >={OFFSET HERE}

A note: This solution will only work in SQL Server 2005 or above, since this was when ROW_NUMBER() was implemented.

Solution 4 - Sql

You can use ROW_NUMBER in a Common Table Expression to achieve this.

;WITH My_CTE AS
(
     SELECT
          col1,
          col2,
          ROW_NUMBER() OVER(ORDER BY col1) AS row_number
     FROM
          My_Table
     WHERE
          <<<whatever>>>
)
SELECT
     col1,
     col2
FROM
     My_CTE
WHERE
     row_number BETWEEN @start_row AND @end_row

Solution 5 - Sql

Specifically for SQL-SERVER you can achieve that in many different ways.For given real example we took Customer table here.

Example 1: With "SET ROWCOUNT"

SET ROWCOUNT 10
SELECT CustomerID, CompanyName from Customers
ORDER BY CompanyName

To return all rows, set ROWCOUNT to 0

SET ROWCOUNT 0  
SELECT CustomerID, CompanyName from Customers
    ORDER BY CompanyName

Example 2: With "ROW_NUMBER and OVER"

With Cust AS
( SELECT CustomerID, CompanyName,
ROW_NUMBER() OVER (order by CompanyName) as RowNumber 
FROM Customers )
select *
from Cust
Where RowNumber Between 0 and 10

Example 3 : With "OFFSET and FETCH", But with this "ORDER BY" is mandatory

SELECT CustomerID, CompanyName FROM Customers
ORDER BY CompanyName
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY

Hope this helps you.

Solution 6 - Sql

For me the use of OFFSET and FETCH together was slow, so I used a combination of TOP and OFFSET like this (which was faster):

SELECT TOP 20 * FROM (SELECT columname1, columname2 FROM tablename
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname

Note: If you use TOP and OFFSET together in the same query like:

SELECT TOP 20 columname1, columname2 FROM tablename
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS

Then you get an error, so for use TOP and OFFSET together you need to separate it with a sub-query.

And if you need to use SELECT DISTINCT then the query is like:

SELECT TOP 20 FROM (SELECT DISTINCT columname1, columname2
    WHERE <conditions...> ORDER BY columname1 OFFSET 100 ROWS) aliasname

Note: The use of SELECT ROW_NUMBER with DISTINCT did not work for me.

Solution 7 - Sql

-- @RowsPerPage  can be a fixed number and @PageNumber number can be passed 
DECLARE @RowsPerPage INT = 10, @PageNumber INT = 2

SELECT *

FROM MemberEmployeeData

ORDER BY EmployeeNumber

OFFSET @PageNumber*@RowsPerPage ROWS

FETCH NEXT 10 ROWS ONLY

Solution 8 - Sql

Adding a slight variation on Aaronaught's solution, I typically parametrize page number (@PageNum) and page size (@PageSize). This way each page click event just sends in the requested page number along with a configurable page size:

begin
	with My_CTE  as
	(
		 SELECT col1,
              ROW_NUMBER() OVER(ORDER BY col1) AS row_number
     FROM
          My_Table
     WHERE
          <<<whatever>>>
	)
	select * from My_CTE
			WHERE RowNum BETWEEN (@PageNum - 1) * (@PageSize + 1) 
							  AND @PageNum * @PageSize
				
end

Solution 9 - Sql

Another sample :

declare @limit int 
declare @offset int 
set @offset = 2;
set @limit = 20;
declare @count int
declare @idxini int 
declare @idxfim int 
select @idxfim = @offset * @limit
select @idxini = @idxfim - (@limit-1);
WITH paging AS
	(
		SELECT 
			 ROW_NUMBER() OVER (order by object_id) AS rowid, *
		FROM 
			sys.objects 
	)
select *
	from 
		(select COUNT(1) as rowqtd from paging) qtd, 
            paging 
	where 
		rowid between @idxini and @idxfim
	order by 
		rowid;
	

Solution 10 - Sql

There is here someone telling about this feature in sql 2011, its sad they choose a little different keyword "OFFSET / FETCH" but its not standart then ok.

Solution 11 - Sql

The closest I could make is

select * FROM( SELECT *, ROW_NUMBER() over (ORDER BY ID ) as ct from [db].[dbo].[table] ) sub where ct > fromNumber  and ct <= toNumber

Which I guess similar to select * from [db].[dbo].[table] LIMIT 0, 10

Solution 12 - Sql

select top (@TakeCount) * --FETCH NEXT
from(
	Select  ROW_NUMBER() OVER (order by StartDate) AS rowid,*
	From YourTable
)A
where Rowid>@SkipCount --OFFSET

Solution 13 - Sql

@nombre_row :nombre ligne par page	
@page:numero de la page

//--------------code sql---------------

declare  @page int,@nombre_row int;
    set @page='2';
    set @nombre_row=5;
    SELECT  *
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY etudiant_ID ) AS RowNum, *
      FROM      etudiant
     
    ) AS RowConstrainedResult
WHERE   RowNum >= ((@page-1)*@nombre_row)+1
    AND RowNum < ((@page)*@nombre_row)+1
ORDER BY RowNum

Solution 14 - Sql

Since nobody provided this code yet:

SELECT TOP @limit f1, f2, f3...
FROM t1
WHERE c1 = v1, c2 > v2...
AND
    t1.id NOT IN
        (SELECT TOP @offset id
         FROM t1
         WHERE c1 = v1, c2 > v2...
         ORDER BY o1, o2...)
ORDER BY o1, o2...

Important points:

  • ORDER BY must be identical
  • @limit can be replaced with number of results to retrieve,
  • @offset is number of results to skip
  • Please compare performance with previous solutions as they may be more efficient
  • this solution duplicates where and order by clauses, and will provide incorrect results if they are out of sync
  • on the other hand order by is there explicitly if that's what's needed

Solution 15 - Sql

Elaborating the Somnath-Muluk's answer just use:

SELECT *
FROM table_name_here
ORDER BY (SELECT NULL AS NOORDER)
OFFSET 9 ROWS 
FETCH NEXT 25 ROWS ONLY 

w/o adding any extra column. Tested in SQL Server 2019, but I guess could work in older ones as well.

Solution 16 - Sql

In SQL server you would use TOP together with ROW_NUMBER()

Solution 17 - Sql

Since, I test more times this script more useful by 1 million records each page 100 records with pagination work faster my PC execute this script 0 sec while compare with mysql have own limit and offset about 4.5 sec to get the result.

Someone may miss understanding Row_Number() always sort by specific field. In case we need to define only row in sequence should use:

ROW_NUMBER() OVER (ORDER BY (SELECT NULL))

SELECT TOP {LIMIT} * FROM (
      SELECT TOP {LIMIT} + {OFFSET} ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS ROW_NO,*
      FROM  {TABLE_NAME}
) XX WHERE ROW_NO > {OFFSET}

Explain:

  • {LIMIT}: Number of records for each page
  • {OFFSET}: Number of skip records

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
QuestionEarlzView Question on Stackoverflow
Solution 1 - SqlSomnath MulukView Answer on Stackoverflow
Solution 2 - SqlAaronaughtView Answer on Stackoverflow
Solution 3 - SqljorgeuView Answer on Stackoverflow
Solution 4 - SqlTom HView Answer on Stackoverflow
Solution 5 - SqlHumayoun_KabirView Answer on Stackoverflow
Solution 6 - SqlsebasdevView Answer on Stackoverflow
Solution 7 - SqlshakeelView Answer on Stackoverflow
Solution 8 - SqlTomView Answer on Stackoverflow
Solution 9 - SqlsillyimView Answer on Stackoverflow
Solution 10 - SqlkeepkeywordspleeeeaseView Answer on Stackoverflow
Solution 11 - Sqluser2991730View Answer on Stackoverflow
Solution 12 - SqlBarnyView Answer on Stackoverflow
Solution 13 - Sqlnoureddine ahmer el kaabView Answer on Stackoverflow
Solution 14 - Sqlprzemo_liView Answer on Stackoverflow
Solution 15 - SqlMike97View Answer on Stackoverflow
Solution 16 - SqlSQLMenaceView Answer on Stackoverflow
Solution 17 - SqlVanda RosView Answer on Stackoverflow