SQL Case Gdy nie oznaczasz wartości null

Oct 04 2020

Próbuję rozwiązać ten problem z kodem Leet :

Napisz zapytanie SQL, aby uzyskać drugą najwyższą pensję z tabeli Employee.

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

Na przykład, biorąc pod uwagę powyższą tabelę Pracownik, zapytanie powinno zwrócić 200 jako drugie najwyższe wynagrodzenie. Jeśli nie ma drugiego najwyższego wynagrodzenia, zapytanie powinno zwrócić wartość null.

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

Próbuję podać takie rozwiązanie:

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

Kiedy jest druga pensja, działa dobrze i zwraca wynik. Jeśli jednak nie ma drugiej pensji i jest tylko jedna pensja, zwracany jest tylko pusty ciąg. Próbuję zwrócić NULL, jednak nie zwraca NULLtego, co napisałem w zapytaniu. Jak mogę to naprawić?

Odpowiedzi

3 Barmar Oct 04 2020 at 07:11

Twoje CASEwyrażenie testuje wynagrodzenie w każdym wierszu tabeli, a nie w tym wybranym przez LIMITklauzulę. Kolejność jest wykonywana po wygenerowaniu wartości na SELECTliście, ponieważ można sortować według obliczonych wartości.

Ponieważ żadna z pensji nie jest pustymi ciągami, warunek w twoim CASEnigdy nie będzie prawdziwy, więc zawsze zwraca Salarywartość. W rezultacie twoje zapytanie jest równoważne z

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

Inne rzeczy:

  1. Musisz użyć, DESCaby uzyskać najwyższą pensję na początku. Więc nawet jeśli twoja metoda zadziała, przyniesie ona drugie najniższe wynagrodzenie.
  2. Twoja metoda nie radzi sobie z przypadkiem, w którym wielu pracowników ma najwyższe wynagrodzenie. LIMIT 1, 1zwróci drugi wiersz, którym będzie jeden z powiązanych pracowników.

Możesz rozwiązać drugi problem, używając podzapytania, które usuwa duplikaty:

SELECT DISTINCT Salary
FROM Employee

Więc ostatnie zapytanie może brzmieć:

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

Na przykład

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

Możesz skorzystać z tego rozwiązania, w którym jeśli nie ma drugiej najwyższej pensji, zwróci NULL. W przeciwnym razie zwróci drugie najwyższe wynagrodzenie

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

Lub jeśli chcesz, aby wartość domyślna DB miała wartość null, po prostu usuń warunek IFNULL

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