datarekha
SQL Medium Asked at AmazonAsked at GoogleAsked at MicrosoftAsked at Goldman Sachs

Write a query to find the Nth highest salary in a table, where N is a parameter, handling ties correctly.

The short answer

Use DENSE_RANK() to assign rank without gaps — the Nth distinct salary value is the row where DENSE_RANK equals N. RANK() would produce wrong results when ties occur, and a plain ORDER BY LIMIT/OFFSET approach ignores ties entirely.

How to think about it

This is a classic ranking question, and the trap is sitting in the data: what happens when two people share the top salary? The interviewer wants to see whether you reach for DENSE_RANK (correct) or reflexively grab RANK or LIMIT/OFFSET (wrong under ties).

Three ranking functions differ only in how they treat ties:

FunctionTiesGap after a tie?
ROW_NUMBER()arbitrary tiebreak, every row uniqueno
RANK()tied rows share a rank, next rank skipsyes — 1, 1, 3
DENSE_RANK()tied rows share a rank, next is consecutiveno — 1, 1, 2

For “Nth highest salary” you need DENSE_RANK: with two people tied at rank 1, RANK jumps straight to 3 and “rank 2” never exists.

A worked example

The data has a tie at the top (two on 120,000) and a tie at the bottom (two on 72,000). Watch how DENSE_RANK numbers the distinct salary levels:

SELECT id, name, salary,
       DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employees
ORDER BY rnk, id;
idnamesalaryrnk
1Aarav1200001
2Bea1200001
3Chen950002
4Dara800003
5Eli720004
6Farah720004

Both 120,000 earners share rank 1, and the next salary (95,000) is rank 2, not 3 — no gap. So the 2nd-highest salary is found by filtering that rank:

SELECT id, name, salary, rnk
FROM (
  SELECT id, name, salary,
         DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
  FROM employees
)
WHERE rnk = 2;
idnamesalaryrnk
3Chen950002

Change rnk = 2 to any N for the Nth-highest. Had you used RANK() here, the 95,000 row would carry rank 3, and WHERE rnk = 2 would return zero rows even though a clear second-highest salary exists.

Why LIMIT/OFFSET is wrong

-- fragile: dedupe-then-skip, breaks when the (N-1)th salary is tied
SELECT DISTINCT salary FROM employees ORDER BY salary DESC LIMIT 1 OFFSET 1;

DISTINCT + OFFSET can accidentally give the right answer on clean data, but it expresses no intent and stumbles on tie patterns. DENSE_RANK says exactly what you mean. It also degrades gracefully: filter WHERE rnk = 10 when only 4 distinct salaries exist and you get zero rows — a clean signal to the caller that N is out of range.

Learn it properly Ranking functions

Keep practising

All SQL questions

Explore further

Skip to content