Urggggg! I\'ve been struggling with this for a long time! I can do it with MySQL so easy but not with SQL Server :(
Here are the simplified tables which should be jo
Here is how I did it a long time ago..
SELECT * FROM (
SELECT TOP y * FROM (
SELECT TOP x * FROM sometable
ORDER BY somefield ASC
)
ORDER BY somefield DESC)
ORDER BY somefield
The innermost query, SELECT TOP x, grabs the first x number of rows, the second query SELECT TOP y, gets the last y of x rows, and the outermost query, SELECT * puts the results in the right order.
Here is a blog post that explains how it works Here is a blog article I wrote back in 2006 talking about it http://code.rawlinson.us/2006/12/t-sql-query-paging.html
The tl;dr; of the post is from this paragraph:
For example, let’s say we want the first page, so the top 20 results. That is pretty easy, just use SELECT TOP 20 …. but what about the second or subsequent pages? How do you get the 21-40 items? It’s easier than you might suspect. What you are actually trying to get is the bottom y of the top x results. To look at that another way you want the top y of the top x results ordered backwards.
It's up to you how you calculate and provide the x and y values to the query.
Try this with Sql Server 2008 + AdventureWorks database
DECLARE @PageIndex INT, @RowsPerPage INT
DECLARE @StartRow INT, @EndRow INT;
SET @PageIndex = 1;
SET @RowsPerPage = 500;
SET @StartRow = ((@PageIndex - 1) * @RowsPerPage) + 1;
SET @EndRow = @StartRow + @RowsPerPage - 1;
--append#1
WITH PAGE_ROWS
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY OrderDate DESC, SalesOrderNumber ASC) AS ROW_NO
, COUNT(*) OVER() AS TOTAL_ROWS
, *
FROM(
--working query
SELECT S.SalesOrderID
, S.SalesOrderNumber
, S.OrderDate
, S.DueDate
, S.ShipDate
, S.Status
, S.PurchaseOrderNumber
, C.AccountNumber
, P.FirstName, P.MiddleName, P.LastName
FROM [Sales].[SalesOrderHeader] AS S
LEFT OUTER JOIN [Sales].[Customer] AS C ON C.CustomerID=S.CustomerID
LEFT OUTER JOIN [Person].[Person] AS P ON P.BusinessEntityID=C.PersonID
--append#2
) AS Src)
SELECT CEILING(TOTAL_ROWS/ CAST(@RowsPerPage AS DECIMAL(20,2))) AS TOTAL_PAGES
,*
FROM PAGE_ROWS
WHERE ROW_NO BETWEEN @StartRow AND @EndRow
ORDER BY OrderDate DESC, SalesOrderNumber ASC
Microsoft added native paging features in SQL Server 2012 and above using "OFFSET" and "FETCH". You can use this feature as below:
-- Skip the first 500 rows and return the next 100
SELECT *
FROM TableName
ORDER BY [ID]
OFFSET 500 ROWS
FETCH NEXT 100 ROWS ONLY;
For the OFFSET __
and FETCH NEXT __
clauses, you can specify constant values (as above), or you can specify variables, expressions, or constant scalar subqueries.