There are four different system functions within SQL 2008 that allow you to rank your data sets.
First of all I’d like to mention the OVER() clause which is applied to all ranking functions. The OVER() clause essentially tells SQL which way (ascending or descending) rows should be ranked, and if the rankings should be grouped, or partitioned, in any way. SQL keyword “OVER()” has other uses, and the above only applies to its use within a ranking function.
ROW_NUMBER()
The first ranking function I’d like to discuss, and probably the easiest to grasp, is ROW_NUMBER(). This function applies a rank based on where in the result set the result appears. If it’s second in the result set, rank 2 will be applied.
SELECT Name,
Age,
ROW_NUMBER() OVER(ORDER BY Age ASC)
FROM Person
The above example would return a persons name and age, as well as their “rank” within the result set. OVER(ORDER BY Age ASC) is ordering the ranking by age in an ascending order. For example, if the result set consisted of 3 people – one aged 1, one aged 4, and one aged 16. The record with the Age of 1 would have a rank of 1, the record with the age of 4 would have a rank of 2, and the final record with an age of 16 would have a rank of 3. If we replaced ASC with DESC in the query, the result set would be the same – but with different ranks. 16 would be rank 1, 4 ranked 2 (as it’s in the middle, it wouldn’t change), and 1 ranked 3.
RANK()
Next we have RANK():
SELECT Name,
Age,
RANK() OVER(ORDER BY Age ASC)
FROM Person
If the above query was applied to a result set with two people aged 12, one person aged 14, and one person aged 18 – then both of the people aged 12 would be rank 1, the person aged 14 would be rank 3 (because two people have already been returned, making the next tank available 3), and the person aged 18 would be rank 4. Again, if we changed ASC with DESC then the person aged 18 would be rank 1, 14 rank 2, and the two people age 12 would both be rank 3.
DENSE_RANK()
DENSE_RANK() is very similar to RANK(), I’ll be using the same example from the RANK() explanation to explain DENSE_RANK(). :
SELECT Name,
Age,
DENSE_RANK() OVER(ORDER BY Age ASC)
FROM Person
This time, the rankings are worked out in the exact same way as with RANK(), but instead of skipping a number if there are two people with the same age – it will apply the next value directly after the previous value.
Both people aged 12 would be rank 1, the person aged 14 would be rank 2, and the person aged 18 would be rank 3 in the case. Making the ranking values more “dense”.
NTILE()
SELECT Name,
Age,
NTILE(2) OVER(ORDER BY Age ASC)
FROM Person
This function is the “odd one out”, if you will, of all the ranking functions. NTILE() is the only ranking function which accepts a parameter. The value passed in must be an integer value of 1 or greater. The value passed in is used to break the result sets into groups, and rank by those groups.
For example, if we passed in a value of 1, and the above query returned 4 results, then all 4 rows would have a rank of 1. If we passed in 2, like in the example code, then the first 2 records (the two with the lowest ages) would be rank 1, and the other two (the older two) would be rank 2.
For the inquisitive types who may be wondering what happens when there isn’t an even number of results – if there are 7 records, and you pass in an even number (such as 2), then the first 4 records would be rank 1, and the last 3 would be rank 2.
PARTITION BY
All of the ranking functions have another option which can be placed in the OVER() clause. This is the PARTITION BY clause, and it’s used to apply ranks within groups, or partitions.
SELECT Name,
Age,
ROW_NUMBER() OVER(PARTITION BY Age ORDER BY Age ASC)
FROM Person
Using the above query, imagine that we have a result of three people aged 10, another three people aged 20, and one person aged 25. The three people aged 10 will be ranked from 1 to 3, then the three people aged 20 will again be ranked 1 to 3, the person aged 25 will be ranked 1. This is because they have been separated into their own ranking groups because they have the same age.