SQL · easy

Write a query to find the second highest salary from an Employees table.

Asked in Data Analyst interviews, in the SQL round.

Short answer

Use a subquery with MAX where salary < (SELECT MAX(salary)), or DENSE_RANK() = 2.

Sample data

These tables are loaded into an in-browser engine on this page, so you can run your own answer against them. No account needed.

employees

idnamedepartmentsalary
1Ada ChenEngineering168000
2Ben OseiEngineering168000
3Cara DiazEngineering151000
4Dev PatelData139000
5Elena RuizData128000
6Grace KimSales98000
7Hugo LindSales104000
8Iris NovakSales91000

How to answer it

Definition

Return the second largest DISTINCT salary. The word that matters is distinct: if two people share the top salary, the second highest is the next value down, not the second row.

Two answers

The subquery version reads like the sentence: the largest salary smaller than the largest salary.

SELECT MAX(salary) AS second_highest
FROM   employees
WHERE  salary < (SELECT MAX(salary) FROM employees);

The window version generalises to Nth and is the one that shows you know window functions.

SELECT DISTINCT salary
FROM (
  SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
  FROM   employees
) ranked
WHERE rnk = 2;

Output

second_highest
--------------
        168000

Why DENSE_RANK and not the others

salary   ROW_NUMBER   RANK   DENSE_RANK
168000            1      1            1
168000            2      1            1
151000            3      3            2

ROW_NUMBER would call the second 168000 the runner-up, which is wrong. RANK skips 2 entirely and returns nothing. DENSE_RANK gives the second distinct value, which is what the question asked for.

Key points

FAQ

The 30-second answer

The subtlety is that they want the second distinct salary, not the second row, so ties have to collapse. I would use DENSE_RANK ordered by salary descending and take rank two, because DENSE_RANK is the one that treats tied salaries as a single rank. ROW_NUMBER would call a tied top earner the runner-up, and RANK would skip rank two altogether and return nothing.
The quick version is MAX of salary where salary is less than the overall MAX, which reads well but only answers second, not Nth. Either way I would say what happens when every salary is identical: you get no row back.

In the interview

Practice this for real