Question presented to candidate: "Say we pay a bonus to the top 3 sales reps in each region, and some reps have exactly the same revenue. Would you use ROW_NUMBER, RANK or DENSE_RANK to pick them? When does the difference actually change the result, and how do you decide?"
What a strong answer should cover:
- The functions only differ on ties, so the choice is a business question: should ties share a place, and should "top N" mean N rows, N places or N distinct values?
WHERE rn <= NwithROW_NUMBERalways returns at most N rows per group but drops tied rows arbitrarily unless there is a business tiebreaker;RANK <= Nreturns every row tied at the boundary (can be more than N);DENSE_RANK <= Nreturns N distinct values (can be many more rows)- The gap matters for equality filters:
RANK() = 2returns nothing after a tie for first, whileDENSE_RANK() = 2means "the second-highest value" (the Nth highest salary pattern) ROW_NUMBERwith a unique tiebreaker is the tool for dedup and "latest row per key";RANK = 1there can return two rows- Equivalents and performance:
FETCH FIRST n ROWS WITH TIES(PostgreSQL 13+) behaves likeRANK <= nfor one group; PostgreSQL 15+ can stop a WindowAgg early on these filters
Clarifying questions expected:
- If two reps tie at the cut-off, do both get the bonus, or do we need exactly three people?
- Is there a natural tiebreaker (earlier close date, lower id), or would picking one be arbitrary?
- Does "top 3" mean three people or the three highest revenue figures?
Code / implementation expected: Yes — the same "top 3" filter with all three functions, showing the different row counts.
Schema used by the examples: