ROW_NUMBER (Transact-SQL)
Returns the sequential number of a row within a partition of a result set, starting at 1 for the first row in each partition.
A. Returning the row number for salespeople
The following example returns the ROW_NUMBER for the salespeople in AdventureWorks2008R2 based on the year-to-date sales.
SELECT FirstName, LastName, ROW_NUMBER() OVER(ORDER BY SalesYTD DESC) AS 'Row Number', SalesYTD, PostalCode FROM Sales.vSalesPerson WHERE TerritoryName IS NOT NULL AND SalesYTD <> 0;
B. Returning a subset of rows
The following example returns rows with numbers 50 to 60 inclusive in the order of the OrderDate.
USE AdventureWorks2008R2;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS 'RowNumber'
FROM Sales.SalesOrderHeader
)
SELECT *
FROM OrderedOrders
WHERE RowNumber BETWEEN 50 AND 60;
C. Using ROW_NUMBER() with PARTITION
The following example shows using the ROW_NUMBER function with the PARTITION BY argument.
SELECT FirstName, LastName, ROW_NUMBER() OVER(PARTITION BY PostalCode ORDER BY SalesYTD DESC) AS 'Row Number', SalesYTD, PostalCode FROM Sales.vSalesPerson WHERE TerritoryName IS NOT NULL AND SalesYTD <> 0;
More useful example
The given example for row_number over partition achieves little as postal codes are unique for all salespeople. Note the last 'order by' partition overrides the previous
use AdventureWorks2008
go
SELECT TerritoryGroup, TerritoryName,
FirstName, LastName,
SalesLastYear,
ROW_NUMBER() OVER(PARTITION BY TerritoryGroup ORDER BY SalesLastYear DESC) AS 'Rank Last Year',
SalesYTD,
ROW_NUMBER() OVER(PARTITION BY TerritoryGroup ORDER BY SalesYTD DESC) AS 'Sales Rank'
FROM Sales.vSalesPerson
WHERE TerritoryName IS NOT NULL
AND SalesYTD <> 0;