Zagnieżdżone zapytania w SQL

Język SQL umożliwia zagnieżdżanie jednego zapytania w innym zapytaniu. Dzięki temu możliwe jest napisanie jednego bardzo dużego zapytania, które zrobi coś dużego i złożonego, chociaż czytelność kodu jest znacznie ograniczona.

W zależności od tego, ile wartości zwracają podzapytania, zmienia się obszar, w którym można je zastosować. W sumie są trzy opcje:

  • Podzapytanie zwraca jedną wartość (jedna kolumna i jeden wiersz).
  • Podzapytanie zwraca listę wartości (tabelę z jedną kolumną).
  • Podzapytanie zwraca tabelę (wiele kolumn, dowolna liczba wierszy).

Spójrzmy na jeden przykład dla każdego przypadku.

Podzapytanie z wynikiem skalarnym

Znajdźmy listę wszystkich naszych pracowników z tabeli pracowników, których wynagrodzenie jest wyższe niż średnia dla firmy. Jak możemy to zrobić?

Możemy łatwo filtrować pracowników, porównując ich wynagrodzenie ze średnią, jeśli znamy ją z góry. Jednocześnie napisaliśmy już zapytanie, które pozwala nam obliczyć średnie wynagrodzenie pracowników firmy. Zapamiętajmy to:

SELECT AVG(salary) FROM employee 

Następnie MySQL zwrócił nam wartość: 76833.3333 .

Jak teraz znaleźć listę wszystkich pracowników, których zarobki są powyżej średniej? To również bardzo proste:

 SELECT * FROM employee 
   WHERE salary > 76833.3333 

Wynikiem tego zapytania będzie:

ID nazwa zawód wynagrodzenie
1 Iwanow Iwan Programista 100000
2 Pietrow Pietr Programista 80000
4 Rabinowicz Mojsza Dyrektor 200000

A teraz po prostu łączymy oba żądania, podstawiając pierwsze żądanie zamiast wartości 76833:

   SELECT * FROM employee 
   WHERE salary > (SELECT AVG(salary) FROM employee) 

Wynik tego zapytania będzie taki sam:

ID nazwa zawód wynagrodzenie
1 Iwanow Iwan Programista 100000
2 Pietrow Pietr Programista 80000
4 Rabinowicz Mojsza Dyrektor 200000

Podzapytanie z listą wartości

Czy pamiętasz, że kiedyś mieliśmy zadanie - znaleźć wszystkie rekordy z jednej tabeli, dla których nie ma odpowiednich rekordów z innej?

Było też takie zdjęcie:

Jeśli się nie mylę, zadanie wygląda następująco: wyświetl listę wszystkich pracowników z tabeli pracowników, dla których nie ma zadań w tabeli zadań .

Znajdźmy również rozwiązanie w dwóch krokach.

Najpierw napiszmy zapytanie, które zwróci id wszystkich pracowników, którzy mają zadania w tabeli zadań. Pamiętaj tylko o dwóch rzeczach:

  • usuń duplikaty - użyj słowa kluczowego DISTINCT.
  • usuń wartości NULL z wyniku.
SELECT DISTINCT employee_id FROM task 
   WHERE employee_id IS NOT NULL

I oto otrzymaliśmy piękny wynik takiej prośby:

dowód pracownika
1
2
5
4
6

Zapiszmy to tymczasowo dla wygody jako ciąg: 1,2,5,4,6. Teraz napiszmy drugie zapytanie - do tabeli pracowników, które zwróci listę pracowników, których id nie znajduje się na pierwszej liście:

SELECT * FROM employee  
WHERE id NOT IN (1,2,5,4,6)

I wynik tego zapytania:

ID nazwa zawód wynagrodzenie wiek data_dołączenia
3 Iwanow Siergiej Próbnik 40000 trzydzieści 2014-01-01

A teraz, podobnie jak w poprzednim przykładzie, możesz połączyć oba żądania, po prostu zastępując treść pierwszego żądania zamiast listy id.

 SELECT * FROM employee 
   WHERE id NOT IN ( 
      	SELECT DISTINCT employee_id FROM task 
      	WHERE employee_id IS NOT NULL 
   )