LIMIT 10..20 in SQL Server

SqlSql ServerPaginationLimit

Sql Problem Overview


I'm trying to do something like :

SELECT * FROM table LIMIT 10,20

or

SELECT * FROM table LIMIT 10 OFFSET 10

but using SQL Server

The only solution I found looks like overkill:

SELECT * FROM ( 
  SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases 
 ) a WHERE row > 5 and row <= 10

I also found:

SELECT TOP 10 * FROM stuff; 

... but it's not what I want to do since I can't specify the starting limit.

Is there another way for me to do that ?

Also, just curious, is there a reason why doesn't SQL Server support the LIMIT function or something similar? I don't want to be mean, but that really sounds like something a DBMS needs ... If it does, then I'm sorry for being so ignorant! I've been working with MySQL and SQL+ for the past 5 years so...

Sql Solutions


Solution 1 - Sql

For SQL Server 2012 + you can use.

SELECT  *
FROM     sys.databases
ORDER BY name 
OFFSET  5 ROWS 
FETCH NEXT 5 ROWS ONLY 

Solution 2 - Sql

The LIMIT clause is not part of standard SQL. It's supported as a vendor extension to SQL by MySQL, PostgreSQL, and SQLite.

Other brands of database may have similar features (e.g. TOP in Microsoft SQL Server), but these don't always work identically.

It's hard to use TOP in Microsoft SQL Server to mimic the LIMIT clause. There are cases where it just doesn't work.

The solution you showed, using ROW_NUMBER() is available in Microsoft SQL Server 2005 and later. This is the best solution (for now) that works solely as part of the query.

Another solution is to use TOP to fetch the first count + offset rows, and then use the API to seek past the first offset rows.

See also:

Solution 3 - Sql

as you found, this is the preferred sql server method:

SELECT * FROM ( 
  SELECT *, ROW_NUMBER() OVER (ORDER BY name) as row FROM sys.databases 
 ) a WHERE a.row > 5 and a.row <= 10

Solution 4 - Sql

How about this?

SET ROWCOUNT 10 

SELECT TOP 20 *
FROM sys.databases
ORDER BY database_id DESC

It gives you the last 10 rows of the first 20 rows. One drawback is that the order is reversed, but, at least it's easy to remember.

Solution 5 - Sql

If you are using SQL Server 2012+ vote for Martin Smith's answer and use the OFFSET and FETCH NEXT extensions to ORDER BY,

If you are unfortunate enough to be stuck with an earlier version, you could do something like this,

WITH Rows AS
(
    SELECT
              ROW_NUMBER() OVER (ORDER BY [dbo].[SomeColumn]) [Row]
            , *
        FROM
              [dbo].[SomeTable]
)
SELECT TOP 10
          *
     FROM
         Rows
    WHERE Row > 10

I believe is functionaly equivalent to

SELECT * FROM SomeTable LIMIT 10 OFFSET 10 ORDER BY SomeColumn

and the best performing way I know of doing it in TSQL, before MS SQL 2012.


If there are very many rows you may get better performance using a temp table instead of a CTE.

Solution 6 - Sql

Unfortunately, the ROW_NUMBER() is the best you can do. It's actually more correct, because the results of a limit or top clause don't really have meaning without respect to some specific order. But it's still a pain to do.

Update: Sql Server 2012 adds a limit -like feature via OFFSET and FETCH keywords. This is the ansi-standard approach, as opposed to LIMIT, which is a non-standard MySql extension.

Solution 7 - Sql

SELECT TOP 10 *
FROM TABLE
WHERE IDCOLUMN NOT IN (SELECT TOP 10 IDCOLUMN FROM TABLE)

Should give records 11-20. Probably not too efficient if incrementing to get further pages, and not sure how it might be affected by ordering. Might have to specify this in both WHERE statements.

Solution 8 - Sql

A good way is to create a procedure:

create proc pagination (@startfrom int ,@endto int) as
SELECT * FROM ( 
  SELECT *, ROW_NUMBER() OVER (ORDER BY name desc) as row FROM sys.databases 
 ) a WHERE a.row > @startfrom and a.row <= @endto

just like limit 0,2 /////////////// execute pagination 0,4

Solution 9 - Sql

Just for the record solution that works across most database engines though might not be the most efficient:

Select Top (ReturnCount) *
From (
    Select Top (SkipCount + ReturnCount) *
    From SourceTable
    Order By ReverseSortCondition
) ReverseSorted
Order By SortCondition

Pelase note: the last page would still contain ReturnCount rows no matter what SkipCount is. But that might be a good thing in many cases.

Solution 10 - 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

Solution 11 - Sql

select * from (select id,name,ROW_NUMBER() OVER (ORDER BY id  asc) as row
from tableName1) tbl1
where tbl1.row>=10 and tbl1.row<=15

Will print rows from 10 to 15.

Solution 12 - Sql

So far this format is what is working for me (not the best performance though):

SELECT TOP {desired amount of rows} * 
FROM (SELECT *, ROW_NUMBER() OVER (ORDER BY {order columns} asc)__row__ FROM {table})tmp
WHERE __row__ > {offset row count}

A note on the side, paginating over dynamic data can lead to strange/unexpected results.

Solution 13 - Sql

From the MS SQL Server online documentation (http://technet.microsoft.com/en-us/library/ms186734.aspx ), here is their example that I have tested and works, for retrieving a specific set of rows. ROW_NUMBER requires an OVER, but you can order by whatever you like:

WITH OrderedOrders AS
(
  SELECT SalesOrderID, OrderDate,
  ROW_NUMBER() OVER (ORDER BY OrderDate) AS RowNumber
  FROM Sales.SalesOrderHeader 
) 
SELECT SalesOrderID, OrderDate, RowNumber  
FROM OrderedOrders 
WHERE RowNumber BETWEEN 50 AND 60;

Solution 14 - Sql

Use all SQL server: ;with tbl as (SELECT ROW_NUMBER() over(order by(select 1)) as RowIndex,* from table) select top 10 * from tbl where RowIndex>=10

Solution 15 - Sql

 SELECT * FROM users WHERE Id Between 15 and 25

it will print from 15 to 25 as like limit in MYSQl

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
QuestionmarcggView Question on Stackoverflow
Solution 1 - SqlMartin SmithView Answer on Stackoverflow
Solution 2 - SqlBill KarwinView Answer on Stackoverflow
Solution 3 - SqlKM.View Answer on Stackoverflow
Solution 4 - SqlDavid PatrickView Answer on Stackoverflow
Solution 5 - SqlJodrellView Answer on Stackoverflow
Solution 6 - SqlJoel CoehoornView Answer on Stackoverflow
Solution 7 - SqlAndyView Answer on Stackoverflow
Solution 8 - SqlWahaj LatifView Answer on Stackoverflow
Solution 9 - SqlY.B.View Answer on Stackoverflow
Solution 10 - SqlSatish Kumar sonkerView Answer on Stackoverflow
Solution 11 - SqlsjithView Answer on Stackoverflow
Solution 12 - SqlCharlie AffumigatoView Answer on Stackoverflow
Solution 13 - SqlMandrake ButtonView Answer on Stackoverflow
Solution 14 - SqlPhạm Tấn LợiView Answer on Stackoverflow
Solution 15 - SqlSR1View Answer on Stackoverflow