SQL Case When not labeling null

Viewed 396

I'm trying to do this Leet Code Problem:

Write a SQL query to get the second highest salary from the Employee table.

+----+--------+
| Id | Salary |
+----+--------+
| 1  | 100    |
| 2  | 200    |
| 3  | 300    |
+----+--------+

For example, given the above Employee table, the query should return 200 as the second highest salary. If there is no second highest salary, then the query should return null.

+---------------------+
| SecondHighestSalary |
+---------------------+
| 200                 |
+---------------------+

I'm trying to give this solution:

SELECT 
      CASE WHEN Salary = '' 
         THEN NULL 
         ELSE Salary END SecondHighestSalary 
   FROM 
      Employee 
   ORDER BY 
      SecondHighestSalary 
   LIMIT 1,1;

When there is a second salary, it works fine and returns the output. However, when there is no second salary and there's only one salary only an empty string is returned. I'm trying to return NULL, however, it doesn't return NULL like what I wrote in my query. How can I fix this?

3 Answers

Your CASE expression is testing the salary in each row of the table, not the one selected by the LIMIT clause. Ordering is done after generating the values in the SELECT list, since you can order by those calculated values.

Since none of the salaries are empty strings, the condition in your CASE will never be true, so it always returns the Salary value. As a result, your query is equivalent to

SELECT Salary AS SecondHighestSalary
FROM Employee
ORDER BY SecondHighestSalary
LIMIT 1, 1

Other things:

  1. You need to use DESC to get the highest salary at the beginning. So even if your method worked, it would find the second lowest salary.
  2. Your method doesn't handle the case where multiple employees are tied for the highest salary. LIMIT 1, 1 will return the second row, which will be one of the tied employees.

You can solve the second problem using a subquery that removes duplicates:

SELECT DISTINCT Salary
FROM Employee

So a final query could be:

SELECT IF(COUNT(*) > 0, MAX(Salary), NULL) AS SecondHighestSalary
FROM (
    SELECT DISTINCT Salary
    FROM Employee
    ORDER BY Salary DESC
    LIMIT 1, 1
) AS x

You can use this solution, where if there have no second highest salary will return NULL. Otherwise will return second highest salary

SELECT 
   IFNULL(MIN(Salary) , 'NULL') as SecondHighestSalary
FROM
    Employee
WHERE salary > (SELECT MIN(salary)
                 FROM Employee)

Or if you want DB default null then just remove IFNULL condition

SELECT 
   MIN(Salary) as SecondHighestSalary
FROM
    Employee
WHERE salary > (SELECT MIN(salary)
                 FROM Employee)

E.g.

 select max(salary) salary 
   from employee 
 where salary not in 
 (select max(salary) from employee)
Related