In SQL Server, PERCENT_RANK() is a window function that calculates and returns the relative rank of a row within a group of rows, expressed as a value between 0 and 1.
In other words, it returns the percentage of partition values less than the value in the current row, excluding the highest value.
Syntax
The syntax goes like this:
PERCENT_RANK( )
OVER ( [ partition_by_clause ] order_by_clause )
So it doesn’t require or accept any arguments, but it does require an OVER clause with at least an ORDER BY clause.
Example
Here’s an example of using the PERCENT_RANK() function:
SELECT
VendorId,
ProductName,
ProductPrice,
PERCENT_RANK( ) OVER (
ORDER BY ProductPrice
) AS PERCENT_RANK
FROM Products;
Result:
VendorId ProductName ProductPrice PERCENT_RANK -------- ------------------------------- ------------ ------------------ 1004 Bottomless Coffee Mugs (4 Pack) 9.99 0 1003 Hammock 10 0.1111111111111111 1001 Long Weight (green) 11.99 0.2222222222222222 1004 Tea Pot 12.45 0.3333333333333333 1001 Long Weight (blue) 14.75 0.4444444444444444 1001 Left handed screwdriver 25.99 0.5555555555555556 1001 Right handed screwdriver 25.99 0.5555555555555556 1002 Sledge Hammer 33.49 0.7777777777777778 1003 Straw Dog Box 55.99 0.8888888888888888 1003 Chainsaw 245 1
Here, the PERCENT_RANK column displays the percentage rank of the ProductPrice column when sorted in ascending order.
We can see that the values range from 0 to 1. We can also see that two products have the same price (the left and right handed screwdrivers), and so they share the same percentage rank.
Partitioning the Result Set
We can use a PARTITION BY clause in order to partition the result set by a given column. For example, we can partition by vendor:
SELECT
v.VendorName,
p.ProductName,
p.ProductPrice,
PERCENT_RANK( ) OVER (
PARTITION BY p.VendorId
ORDER BY p.ProductPrice
) AS PERCENT_RANK
FROM Products p
INNER JOIN Vendors v
ON v.VendorId = p.VendorId;
Result:
VendorName ProductName ProductPrice PERCENT_RANK ------------- ------------------------------- ------------ ------------------ Mars Supplies Long Weight (green) 11.99 0 Mars Supplies Long Weight (blue) 14.75 0.3333333333333333 Mars Supplies Left handed screwdriver 25.99 0.6666666666666666 Mars Supplies Right handed screwdriver 25.99 0.6666666666666666 Randy Roofers Sledge Hammer 33.49 0 Pedal Medals Hammock 10 0 Pedal Medals Straw Dog Box 55.99 0.5 Pedal Medals Chainsaw 245 1 Katty Kittens Bottomless Coffee Mugs (4 Pack) 9.99 0 Katty Kittens Tea Pot 12.45 1
Here we get the percentage rank within each partition. Therefore the PERCENT_RANK column resets with each new partition.
In this case I used a SQL join to join the Products and Vendors table so that I could present the vendor names instead of just their IDs.
The OVER Clause is Required
We must provide the OVER clause when using the PERCENT_RANK() function. Here’s what happens if we remove it:
SELECT
VendorId,
ProductName,
ProductPrice,
PERCENT_RANK( )
FROM Products;
Result:
Msg 10753, Level 15, State 3, Line 5 The function 'PERCENT_RANK' must have an OVER clause.
The ORDER BY Clause is Required
Furthermore, the OVER clause must have at least an ORDER BY clause. Here’s what happens when we include an OVER clause without an ORDER BY clause:
SELECT
VendorId,
ProductName,
ProductPrice,
PERCENT_RANK( ) OVER ( )
FROM Products;
Result:
Msg 4112, Level 15, State 1, Line 5 The function 'PERCENT_RANK' must have an OVER clause with ORDER BY.