Caso SQL quando não rotulado como nulo

Oct 04 2020

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

3 Barmar Oct 04 2020 at 07:11

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:

  1. 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 .
  2. 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
Strawberry Oct 04 2020 at 06:11

Por exemplo

 select max(salary) salary 
   from employee 
 where salary not in 
 (select max(salary) from employee)
Runa Oct 04 2020 at 06:45

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)