To count the row number in SQL there’s a useful little in built SQL function you need to use, row_number()

This enables you to number all rows and restart the row numbering part way a dataset. Note this is different to the SQL rank function.

This is a very useful thing is you want to select the top X rows by specified criteria. For example the top 10 selling products per country or the top 5 sales people per region.

The syntax of this is ROW_NUMBER ( )     OVER ( [ <partition_by_clause> ] <order_by_clause> ), which for me is not super helpful without some examples. (For more details you can see the row_number function on the Microsoft website here: http://msdn.microsoft.com/en-us/library/ms186734.aspx)

Here is some demo data to run through some common scenarios. You can run this code in SQL Server Management Studio (SSMS) to create the test data.

CREATE TABLE #Sales
    (
    Country varchar(10)
    ,Person varchar(2)
    ,Sales decimal (18,2)
    )

insert into #Sales values (‘UK’,’AW’,8329)
insert into #Sales values (‘UK’,’KS’,542)
insert into #Sales values (‘UK’,’NE’,942)
insert into #Sales values (‘UK’,’LT’,7358)
insert into #Sales values (‘UK’,’AP’,4262)
insert into #Sales values (‘France’,’ME’,952)
insert into #Sales values (‘France’,’DD’,8802)
insert into #Sales values (‘France’,’WQ’,2331)
insert into #Sales values (‘France’,’PD’,544)
insert into #Sales values (‘France’,’ML’,2418)
insert into #Sales values (‘Italy’,’MN’,5426)
insert into #Sales values (‘Italy’,’DN’,7982)
insert into #Sales values (‘Italy’,’IA’,499)
insert into #Sales values (‘Italy’,’EY’,1034)
insert into #Sales values (‘Italy’,’LA’,5429)

Example 1: Number each row with the highest selling person at the top

This is quite simple, you just need to order by sales in the Over part of the clause.

select Person
    ,Country
    ,Sales
    ,ROW_NUMBER() over (order by sales desc) as RowNumber
from #Sales

Example 2: Number each row with the highest selling person at the top doing this for each country

Slightly more complex, this is where we introduce the Partition By into to Over part of the clause

select Country
    ,Person
    ,Sales
    ,ROW_NUMBER() over (partition by country order by sales desc) as RowNumber
from #Sales

Example 3: Only select the top 3 sales people from each country in term of sales amount

Here we also need to use the same code as Example 2 and we just query that result set

select Country
    ,Person
    ,Sales
    ,RowNumber
from
    (
    select Country
        ,Person
        ,Sales
        ,ROW_NUMBER() over (partition by country order by sales desc) as RowNumber
    from #Sales
    )a
where RowNumber < 4
order by Country, RowNumber

Quite straightforward once you understand the syntax. Note the Row_number() function can’t be used in the WHERE clause or HAVING hence I had to query a query in Example 3.