Skip to content

LeetCode 177: Nth Highest Salary

A clear SQL solution for finding the nth highest distinct salary from the Employee table.

Problem Restatement

We are given a table named Employee.

ColumnType
idint
salaryint

Each row stores one employee and that employee’s salary.

We need to write a SQL function that returns the nth highest distinct salary.

If there are fewer than n distinct salaries, the function should return null. The official problem asks for the nth highest distinct salary from Employee, returning null when fewer than n distinct salaries exist.

Input and Output

ItemMeaning
InputTable Employee(id, salary) and integer N
OutputThe Nth highest distinct salary
Function namegetNthHighestSalary(N)
Missing value caseReturn null

Example function shape:

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
    ...
END

Examples

Example 1:

Employee
+----+--------+
| id | salary |
+----+--------+
| 1  | 100    |
| 2  | 200    |
| 3  | 300    |
+----+--------+

N = 2

The distinct salaries in descending order are:

300, 200, 100

The second highest salary is 200.

Output:

+------------------------+
| getNthHighestSalary(2) |
+------------------------+
| 200                    |
+------------------------+

Example 2:

Employee
+----+--------+
| id | salary |
+----+--------+
| 1  | 100    |
+----+--------+

N = 2

There is only one distinct salary.

So the second highest salary does not exist.

Output:

+------------------------+
| getNthHighestSalary(2) |
+------------------------+
| null                   |
+------------------------+

First Thought: Sort Distinct Salaries

The most direct idea is:

  1. Get all distinct salaries.
  2. Sort them from highest to lowest.
  3. Skip the first N - 1 salaries.
  4. Return the next salary.

For example, if salaries are:

300, 200, 100

and N = 2, then we skip 1 salary:

300

The next salary is:

200

So the answer is 200.

Key Insight

SQL already has the tools needed for this problem:

SQL featureRole
DISTINCTRemoves duplicate salary values
ORDER BY salary DESCSorts salaries from highest to lowest
LIMIT 1Takes one salary
OFFSET N - 1Skips the first N - 1 salary levels

The important detail is that OFFSET needs a zero-based index.

So:

NMeaningOFFSET
1highest salary0
2second highest salary1
3third highest salary2

Therefore, we use:

N - 1

as the offset.

Algorithm

Inside the SQL function:

  1. Convert N into an offset by subtracting 1.
  2. Select distinct salaries.
  3. Sort them in descending order.
  4. Skip N - 1 rows.
  5. Return one row.

Correctness

After DISTINCT, each salary level appears once.

After ORDER BY salary DESC, the salary levels are arranged from highest to lowest.

The salary at offset 0 is the highest salary.

The salary at offset 1 is the second highest salary.

In general, the salary at offset N - 1 is the Nth highest distinct salary.

So returning the row at OFFSET N - 1 gives the correct answer.

If there are fewer than N distinct salaries, then the query has no row at that offset. In a scalar return context, this produces null, which matches the required result.

Complexity

MetricValueWhy
TimeO(n log n)The database may sort distinct salary values
SpaceO(n)The database may store distinct salary values during sorting

With an index on salary, the database engine may execute this more efficiently.

Implementation

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
    SET N = N - 1;

    RETURN (
        SELECT DISTINCT salary
        FROM Employee
        ORDER BY salary DESC
        LIMIT 1 OFFSET N
    );
END

Code Explanation

This line converts the rank into an offset:

SET N = N - 1;

If we want the first highest salary, we need offset 0.

If we want the second highest salary, we need offset 1.

Then this query builds the ordered salary list:

SELECT DISTINCT salary
FROM Employee
ORDER BY salary DESC

DISTINCT removes duplicates.

ORDER BY salary DESC puts the highest salaries first.

Finally:

LIMIT 1 OFFSET N

skips the first N rows after the earlier subtraction, then returns one salary.

For example, original N = 2.

After subtraction:

N = 1

Then OFFSET 1 skips the highest salary and returns the next salary.

Testing

Test case 1:

CREATE TABLE Employee (
    id INT PRIMARY KEY,
    salary INT
);

INSERT INTO Employee (id, salary) VALUES
(1, 100),
(2, 200),
(3, 300);

SELECT getNthHighestSalary(2);

Expected:

+------------------------+
| getNthHighestSalary(2) |
+------------------------+
| 200                    |
+------------------------+

Test case 2:

DELETE FROM Employee;

INSERT INTO Employee (id, salary) VALUES
(1, 100);

SELECT getNthHighestSalary(2);

Expected:

+------------------------+
| getNthHighestSalary(2) |
+------------------------+
| null                   |
+------------------------+

Test case 3:

DELETE FROM Employee;

INSERT INTO Employee (id, salary) VALUES
(1, 100),
(2, 100),
(3, 200),
(4, 300),
(5, 300);

SELECT getNthHighestSalary(2);

Distinct salaries:

300, 200, 100

Expected:

+------------------------+
| getNthHighestSalary(2) |
+------------------------+
| 200                    |
+------------------------+

Test case 4:

DELETE FROM Employee;

INSERT INTO Employee (id, salary) VALUES
(1, 100),
(2, 200),
(3, 300);

SELECT getNthHighestSalary(1);

Expected:

+------------------------+
| getNthHighestSalary(1) |
+------------------------+
| 300                    |
+------------------------+