WindowSQL standard

DENSE_RANK

Assigns places with ties, but without gaps: 1, 2, 2, 3.

Syntax

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

Equal values share a place, and the next value gets the next number, with no gap. Handy when it's the levels of values that matter: the highest salary, the second highest, the third.

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.

Places without gaps
SELECT name, salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS place
FROM employees;
namesalaryplace
Olivia13501
Emma12002
Sophia12002
Liam10003
Noah9504

Emma and Sophia share second place, and Liam is third. RANK would put him fourth.

RANK and DENSE_RANK side by side
SELECT name, salary,
RANK() OVER (ORDER BY salary DESC) AS rank,
DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rank
FROM employees;
namesalaryrankdense_rank
Olivia135011
Emma120022
Sophia120022
Liam100043
Noah95054
The second highest salaryAdvanced
SELECT name, salary
FROM (
SELECT name, salary,
DENSE_RANK() OVER (ORDER BY salary DESC) AS place
FROM employees
) ranked
WHERE place = 2;
namesalary
Emma1200
Sophia1200

A classic interview question. DENSE_RANK finds exactly the second value, however many people share it.

Watch out

DENSE_RANK doesn't tell you how many people are above: Liam is in place 3, although three people come before him. If you need the position counting everyone, use RANK.

You can't use the place in the WHERE of the same query — calculate it in a subquery first and filter outside it.

Related functions

Learn more in the course