Interogări imbricate în SQL

Limbajul SQL vă permite să imbricați o interogare într-o altă interogare. Acest lucru face posibilă scrierea unei interogări foarte mari care va face ceva mare și complex, deși lizibilitatea codului este mult redusă.

În funcție de câte valori sunt returnate de subinterogări, zona în care pot fi aplicate se modifică. Există trei opțiuni în total:

  • Subinterogarea returnează o singură valoare (o coloană și un rând).
  • Subinterogarea returnează o listă de valori (un tabel cu o coloană).
  • Subinterogarea returnează un tabel (mai multe coloane, orice număr de rânduri).

Să ne uităm la un exemplu pentru fiecare caz.

Subinterogare cu rezultat scalar

Să găsim o listă cu toți angajații noștri din tabelul de angajați al căror salariu este mai mare decât media pentru companie. Cum putem face acest lucru?

Putem filtra cu ușurință angajații comparând salariul lor cu media dacă o știm dinainte. Totodată, am scris deja o interogare care ne permite să calculăm salariul mediu al angajaților companiei. Să ne amintim:

SELECT AVG(salary) FROM employee 

Apoi MySQL ne-a returnat valoarea: 76833.3333 .

Cum să găsești acum o listă cu toți angajații al căror salariu este peste medie? De asemenea, este foarte simplu:

 SELECT * FROM employee 
   WHERE salary > 76833.3333 

Rezultatul acestei interogări va fi:

id Nume ocupaţie salariu
1 Ivanov Ivan Programator 100000
2 Petrov Petr Programator 80000
4 Rabinovici Moisha Director 200000

Și acum combinăm ambele cereri înlocuind prima cerere în loc de valoarea 76833:

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

Rezultatul acestei interogări va fi același:

id Nume ocupaţie salariu
1 Ivanov Ivan Programator 100000
2 Petrov Petr Programator 80000
4 Rabinovici Moisha Director 200000

Subinterogare cu listă de valori

Îți amintești cândva am avut o sarcină - să găsim toate înregistrările dintr-un tabel pentru care nu există înregistrări corespunzătoare din altul?

Era si aceasta poza:

Dacă nu mă înșel, sarcina este următoarea: afișați o listă cu toți angajații din tabelul de angajați pentru care nu există sarcini în tabelul de sarcini .

Să găsim și o soluție în doi pași.

Mai întâi, să scriem o interogare care va returna id-ul tuturor angajaților care au sarcini în tabelul de sarcini. Nu uitați decât două lucruri:

  • eliminați duplicatele - utilizați cuvântul cheie DISTINCT.
  • eliminați valorile NULL din rezultat.
SELECT DISTINCT employee_id FROM task 
   WHERE employee_id IS NOT NULL

Și aici am obținut un rezultat frumos al unei astfel de solicitări:

card de identitate al angajatului
1
2
5
4
6

Să-l notăm temporar pentru comoditate, ca o secvență: 1,2,5,4,6. Acum să scriem o a doua interogare - în tabelul de angajați, care va returna o listă de angajați al căror id nu este conținut în prima listă:

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

Și rezultatul acestei interogări:

id Nume ocupaţie salariu vârstă Data înscrierii
3 Ivanov Serghei Tester 40000 treizeci 01-01-2014

Și acum, ca și în exemplul anterior, puteți combina ambele solicitări pur și simplu înlocuind corpul primei solicitări în locul listei de id-uri.

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