WindowSQL standard

PERCENT_RANK

Shows a row's relative position from 0 to 1: what share of the other rows comes before it.

Syntax

PERCENT_RANK() OVER (ORDER BY <sort key>)
PERCENT_RANK() OVER (PARTITION BY <group> ORDER BY <sort key>)

Calculates (rank − 1) / (rows − 1): the first in order gets 0, the last gets 1. Handy for saying “earns more than 75% of colleagues”. The similar CUME_DIST calculates the share including the current row and never gives 0.

Data for the examples

employees

namedepartmentsalarybonusphone
Emmabackend1200300+44 7700 900123
Liambackend1000NULLNULL
Oliviafrontend1350150+44 7700 900456
Noahfrontend950NULL+44 7700 900789
Sophiadesign1200200NULL

These tables already exist in the sandbox — the examples below use them. Want to try this in your own database? Copy the SQL.

Relative position by salary
SELECT name, salary,
PERCENT_RANK() OVER (ORDER BY salary) AS percent_rank
FROM employees;
namesalarypercent_rank
Noah9500
Liam10000.25
Emma12000.5
Sophia12000.5
Olivia13501
In percent
SELECT name, salary,
ROUND(PERCENT_RANK() OVER (ORDER BY salary) * 100) AS higher_than_percent
FROM employees;
namesalaryhigher_than_percent
Noah9500
Liam100025
Emma120050
Sophia120050
Olivia1350100

Emma and Sophia earn more than 50% of their colleagues, and Olivia — more than everyone else.

Within each department
SELECT name, department, salary,
PERCENT_RANK() OVER (PARTITION BY department ORDER BY salary) AS rank_in_department
FROM employees;
namedepartmentsalaryrank_in_department
Liambackend10000
Emmabackend12001
Sophiadesign12000
Noahfrontend9500
Oliviafrontend13501

In a department of one — design — the result is 0: there's no one to compare with.

Watch out

The result is a fraction from 0 to 1, not a percentage. For percent, multiply by 100.

Equal values get the same result, so several people can have 0.5 at once.

For a single row the result is 0: there's nothing to divide by.

Related functions

Learn more in the course