Skip to content
datarekha
SQL Medium Asked at GoogleAsked at AmazonAsked at MetaAsked at AppleAsked at Microsoft

Write a query to return the top 3 highest-paid employees in each department.

The short answer

Assign ROWNUMBER() (or DENSERANK() if ties should be included) partitioned by department and ordered by salary descending, then filter in an outer query or CTE where the rank is 3 or less. You cannot filter on a window function directly in WHERE — it must be wrapped.

How to think about it

This is one of the most common SQL interview problems, and it tests three things at once: do you know window functions, do you know why you need a wrapper query, and can you reason about ties?

The why-a-wrapper part is the crux. Window functions are evaluated in the SELECT phase, after WHERE has run — so you can’t write WHERE rn <= 3 in the same query that computes rn. You rank in a CTE, then filter in the outer query.

A worked example

PARTITION BY dept restarts the rank per department; ORDER BY salary DESC makes rank 1 the top earner; the outer WHERE rn <= 3 keeps the top three:

WITH ranked AS (
  SELECT dept, name, salary,
         ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn
  FROM employees
)
SELECT dept, name, salary, rn
FROM ranked
WHERE rn <= 3
ORDER BY dept, salary DESC;
deptnamesalaryrn
EngAarav1200001
EngBea1100002
EngChen1100003
SalesEli800001
SalesFarah720002
SalesGita720003

Three per department, the rank restarting at 1 for Sales. But look closely at the ties: Bea and Chen both earn 110,000, and ROW_NUMBER arbitrarily gave them rn 2 and 3 — a fourth Eng employee on 110,000 would be cut at rn 4 purely by luck of the tiebreak. That’s the decision the interviewer wants you to surface.

Choosing the ranking function

RequirementFunction
Exactly N rows per group, ties broken arbitrarilyROW_NUMBER
Include everyone tied for Nth placeDENSE_RANK
Include ties but skip ranks after themRANK

Swap to DENSE_RANK and three people sharing the third salary all survive <= 3 — potentially more than three rows per department. Whether that’s correct is a business question, so clarify it before coding. (The pre-window alternative — a correlated COUNT(DISTINCT salary > e1.salary) < 3 — is O(n²) and fragile; mention you know it, then pivot to the window version.)

Learn it properly Top-N per group

Keep practising

All SQL questions

Explore further