6

I've been doing a lot of reading on alternatives to the LIMIT clause for SQL SERVER. It's so frustrating that they still refuse to adapt it. Anyway, I really havn't been able to get my head around this. The query I'm trying to convert is this...

SELECT ID, Name, Price, Image FROM Products ORDER BY ID ASC LIMIT $start_from, $items_on_page

Any assistance would be much appreciated, thank you.

idmean
  • 14,540
  • 9
  • 54
  • 83
aelsheikh
  • 2,268
  • 5
  • 26
  • 41

5 Answers5

28

In SQL Server 2012, there is support for the ANSI standard OFFSET / FETCH syntax. I blogged about this and here is the official doc (this is an extension to ORDER BY). Your syntax converted for SQL Server 2012 would be:

SELECT ID, Name, Price, Image 
  FROM Products 
  ORDER BY ID ASC 
  OFFSET (@start_from - 1) ROWS -- not sure if you need -1
    -- because I don't know how you calculated @start_from
  FETCH NEXT @items_on_page ROWS ONLY;

Prior to that, you need to use various workarounds, including the ROW_NUMBER() method. See this article and the follow-on discussion. If you are not on SQL Server 2012, you can't use standard syntax or MySQL's non-standard LIMIT but you can use a more verbose solution such as:

;WITH o AS
(
    SELECT TOP ((@start_from - 1) + @items_on_page)
         -- again, not sure if you need -1 because I 
         -- don't know how you calculated @start_from
      RowNum = ROW_NUMBER() OVER (ORDER BY ID ASC)
      /* , other columns */
    FROM Products
)
SELECT 
    RowNum
    /* , other columns */
FROM
    o
WHERE
    RowNum >= @start_from
ORDER BY
    RowNum;

There are many other ways to skin this cat, this is unlikely to be the most efficient but syntax-wise is probably simplest. I suggest reviewing the links I posted as well as the duplicate suggestions noted in the comments to the question.

Aaron Bertrand
  • 272,866
  • 37
  • 466
  • 490
  • Sorry, Mr.Anon was me. I seem to have down voted the correct answer. I used the second method you mentioned, works a charm :) – aelsheikh Jan 28 '12 at 02:08
4

For SQL Server 2005 and 2008 This is an example query to select rows from 11 to 20 from Report table ordered by LastName.

SELECT a.* FROM 
(SELECT *, ROW_NUMBER() OVER (ORDER BY LastName) as row FROM Report) a
WHERE a.row > 10 and a.row <= 20
Jeremy Cook
  • 20,840
  • 9
  • 71
  • 77
2

Try this:

SELECT TOP $items_on_page ID, Name, Price, Image 
FROM (SELECT TOP $start_from + $items_on_page - 1 * FROM Products ORDER BY ID) as T 
ORDER BY ID DESC

EDIT: Explanation-

No getting around the subquery, but this is an elegant solution. Say you wanted 10 items per page, starting on the 5th row, this would give you the bottom 10 rows of the top 14 rows. Essentially LIMIT 5,10

Jivings
  • 22,834
  • 6
  • 60
  • 101
  • I test your query but it returned this: Incorrect syntax near the keyword 'FROM' – aelsheikh Jan 26 '12 at 21:26
  • Ah no worries, just figured it out. Your code works great, obviously only problem is that might repeat some on the last page of items. Thank you very much – aelsheikh Jan 26 '12 at 21:42
1

you can use ROW COUNT : Returns the number of rows affected by the last statement. when you don, you reset the rowcont.

SET ROWCOUNT 100

or you can try using TOP query

SELECT TOP 100 * FROM Sometable ORDER BY somecolumn
Ravi Gadag
  • 15,735
  • 5
  • 57
  • 83
  • This works great for the first page. Needs to be a little more complicated to get the second, third, and nth page, and also should fail gracefully if you ask for the second page and the table only has 80 rows. – Aaron Bertrand Jan 26 '12 at 03:09
-1

If you allow the application to store a tad of state, you can do this using just TOP items_on_page. What you do is to store the ID of the last item you retrieved, and for each subsequent query add AND ID > [last ID]. So you get the items in batches of items_on_page, starting where you left off each time.

Borealid
  • 95,191
  • 9
  • 106
  • 122
  • Well, basing this on actual data can be a mistake. Data can shift all the time, unless the rows in this table can never be deleted. Also it assumes that the data should be ordered by the ID, but this is not very common - usually data is ordered alphabetically, by relevance, or by price or other user-defined ordering. – Aaron Bertrand Jan 26 '12 at 03:12
  • @AaronBertrand: he sorted by ID in the original query, and it looks to be an assigned increasing identifier. – Borealid Jan 26 '12 at 03:13
  • Understood, but not all readers will have the same requirement or will notice that nuance in the original question. – Aaron Bertrand Jan 26 '12 at 03:16
  • Also, `LIMIT items_on_page` does not work in SQL Server. Did you mean `TOP`? – Aaron Bertrand Jan 26 '12 at 18:15