Caso SQL quando não rotulado como nulo
Estou tentando resolver este problema de código Leet :
Escreva uma consulta SQL para obter o segundo maior salário da tabela Funcionário.
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
Por exemplo, dada a tabela Employee acima, a consulta deve retornar 200 como o segundo maior salário. Se não houver o segundo maior salário, a consulta deve retornar nulo.
+---------------------+
| SecondHighestSalary |
+---------------------+
| 200 |
+---------------------+
Estou tentando dar esta solução:
SELECT
CASE WHEN Salary = ''
THEN NULL
ELSE Salary END SecondHighestSalary
FROM
Employee
ORDER BY
SecondHighestSalary
LIMIT 1,1;
Quando há um segundo salário, funciona bem e retorna o resultado. No entanto, quando não há um segundo salário e há apenas um salário, apenas uma string vazia é retornada. Estou tentando retornar NULL, porém não retorna NULLcomo escrevi na minha consulta. Como posso consertar isso?
Respostas
Sua CASEexpressão está testando o salário em cada linha da tabela, não aquele selecionado pela LIMITcláusula. O pedido é feito após a geração dos valores na SELECTlista, já que você pode ordenar por esses valores calculados.
Como nenhum dos salários são strings vazias, a condição em seu CASEnunca será verdadeira, portanto, sempre retorna o Salaryvalor. Como resultado, sua consulta é equivalente a
SELECT Salary AS SecondHighestSalary
FROM Employee
ORDER BY SecondHighestSalary
LIMIT 1, 1
Outras coisas:
- Você precisa usar
DESCpara obter o salário mais alto no início. Portanto, mesmo que seu método funcionasse, ele encontraria o segundo salário mais baixo . - Seu método não trata do caso em que vários funcionários estão empatados pelo salário mais alto.
LIMIT 1, 1retornará a segunda linha, que será um dos funcionários empatados.
Você pode resolver o segundo problema usando uma subconsulta que remove duplicatas:
SELECT DISTINCT Salary
FROM Employee
Portanto, uma consulta final poderia ser:
SELECT IF(COUNT(*) > 0, MAX(Salary), NULL) AS SecondHighestSalary
FROM (
SELECT DISTINCT Salary
FROM Employee
ORDER BY Salary DESC
LIMIT 1, 1
) AS x
Por exemplo
select max(salary) salary
from employee
where salary not in
(select max(salary) from employee)
Você pode usar esta solução, onde se não houver o segundo maior salário retornará NULL. Caso contrário, retornará o segundo maior salário
SELECT
IFNULL(MIN(Salary) , 'NULL') as SecondHighestSalary
FROM
Employee
WHERE salary > (SELECT MIN(salary)
FROM Employee)
Ou se você quiser o padrão do banco de dados nulo, basta remover a condição IFNULL
SELECT
MIN(Salary) as SecondHighestSalary
FROM
Employee
WHERE salary > (SELECT MIN(salary)
FROM Employee)