anotherbyte.netanother byte

Paging data using SQL

Published
11 Apr 2008
Updated
19 Feb 2009
Paging is one of those things that you wish there was more support for, but you want real control over. I've found a number of ways to do it, each has advantages and drawbacks. These are the two best solutions I've found. I have to list two, as one works only when sorting by unique db fields, and the other is slower but can be sorted by any field.

For data sorted by a unique field (eg. primary key or unique Name field): A More Efficient Method for Paging Through Large Result Sets

For example:
  1. CREATE  PROCEDURE [dbo].[stored_procedure_name]
  2. (
  3. @startRowIndex INT,
  4. @maximumRows INT
  5. )
  6. AS
  7.  
  8. DECLARE @first_id INT, @startRow INT
  9.  
  10. -- A check can be added to make sure @startRowIndex isn't > count(1)
  11. -- from employees before doing any actual work unless it is guaranteed
  12. -- the caller won't do that
  13.  
  14. -- Get the first employeeID for our page of records
  15. SET ROWCOUNT @startRowIndex
  16. SELECT @first_id = employeeID FROM employees ORDER BY employeeid
  17. -- Now, set the row count to MaximumRows and get
  18. -- all records >= @first_id
  19. SET ROWCOUNT @maximumRows
  20.  
  21. SELECT e.*, d.name AS DepartmentName
  22. FROM employees e
  23. INNER JOIN Departments D ON
  24. e.DepartmentID = d.DepartmentID
  25. WHERE employeeid >= @first_id
  26. ORDER BY e.EmployeeID
  27.  
  28. SET ROWCOUNT 0
  29.  
  30. GO


For data that needs to be sorted by a non-unique field, a different approach is needed. There might be a way to adapt the previous method... but I haven't been able to yet.

Easy, yet fast, SQL paging solution

For example:
  1. SELECT TOP 5 *
  2. FROM Books
  3. WHERE BookID
  4. NOT IN (
  5. SELECT TOP 45 BookID
  6. FROM Books
  7. ORDER BY BookID
  8. )
  9. ORDER BY BookID


The problem seems to centre on there being no way to distinguish between rows when sorting by a non-unique field. It is possible to store the primary key, however the sorting is complex.
For example, the first item of a page is test2, below. but since we sort by date, test1 is selected instead.
  1. Name  DATE  
  2. test3  2008-04-09
  3. test2  2008-04-09  
  4. test4 2008-04-09
  5. test1 2008-04-10
  6. test5 2008-04-10


This can be prevented by using a primary key. However, the sorting cannot be maintained, as any subsequent rows with Name > selected row will not sort lower. The goal is to find a way that retrieves items in the exact same order, and allows the selection to start from any row.
blog comments powered by Disqus