TL;DR ⚡
Abstract
- “Find the 2nd highest salary” — know 3 ways: subquery MAX,
LIMIT/OFFSET, and window functionDENSE_RANK().- The trap: duplicates and NULL when there’s no 2nd —
DENSE_RANKhandles ties correctly.
Approach 1 — subquery with MAX (works everywhere)
SELECT MAX(salary) AS second_highest
FROM employees
WHERE salary < (SELECT MAX(salary) FROM employees);“The max salary that is less than the overall max.” Simple, returns NULL if there’s no second. Handles duplicate top salaries correctly (they’re all excluded by < max).
Approach 2 — LIMIT / OFFSET (MySQL/Postgres)
SELECT DISTINCT salary
FROM employees
ORDER BY salary DESC
LIMIT 1 OFFSET 1; -- skip the 1st, take the nextUse DISTINCT so duplicate top salaries don’t make OFFSET land on the same value. (Oracle: FETCH FIRST 1 ROWS ONLY OFFSET 1 ROWS.)
Approach 3 — window function DENSE_RANK (best, handles ties, generalizes to Nth)
SELECT salary FROM (
SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
FROM employees
) t
WHERE rnk = 2;DENSE_RANKgives ties the same rank with no gaps (1,1,2) — so “2nd highest distinct salary” is correct even with duplicates.- Change
= 2to= Nfor the Nth highest — this is why it’s the interview-preferred answer. - Contrast:
RANK()leaves gaps after ties (1,1,3);ROW_NUMBER()gives unique numbers (1,2,3) ignoring ties.
Interview points
- If asked “what if two people share the top salary?” → subquery-MAX and DENSE_RANK handle it; naive OFFSET without DISTINCT breaks.
- “What if there’s no second highest?” → returns NULL / no row.
- Generalize: DENSE_RANK for Nth-highest is the clean, scalable answer.
Test Yourself
Three ways to find 2nd highest salary?::(1) MAX where salary < (SELECT MAX…); (2) ORDER BY DESC LIMIT 1 OFFSET 1 with DISTINCT; (3) DENSE_RANK() window, filter rnk=2.
Why DENSE_RANK over ROW_NUMBER for ‘Nth highest’?::DENSE_RANK gives ties the same rank with no gaps, so duplicates are handled; ROW_NUMBER would give distinct numbers ignoring ties.
How to generalize to Nth highest?::Use DENSE_RANK() OVER (ORDER BY salary DESC) and filter rnk = N.