Principalele subinterogări în comenzile SQL
Subinterogările în SELECT
În expresia SELECT, putem introduce subinterogări în patru moduri:
- În condiția din clauza WHERE
- În condiția din clauza HAVING
- Ca tabel pentru selecție în clauza FROM
- Ca specificație de coloană în clauza SELECT
Să examinăm unele dintre aceste cazuri. De exemplu, să obținem toate produsele cu prețul mai mare decât media:
SELECT * FROM Products
WHERE Price > (SELECT AVG(Price) FROM Products)
Pentru a obține produsele necesare, trebuie să efectuăm inițial o subinterogare pentru a obține prețul mediu al produselor: `SELECT AVG(Price) FROM Products`.
Operatorul IN
Adesea, subinterogările sunt utilizate împreună cu operatorul IN, care selectează dintr-un set de valori. Și subinterogarea poate furniza exact acest set de valori. De exemplu, să selectăm toate produsele din tabela Products pentru care există comenzi în tabela Orders:
SELECT * FROM Products
WHERE Id IN (SELECT ProductId FROM Orders)
Adică, subinterogarea selectează toate identificatoarele produselor din Orders, apoi, folosind aceste identificatoare, se extrag produsele din Products.
Adăugând operatorul NOT, putem selecta produsele pentru care nu există comenzi în tabela Orders:
SELECT * FROM Products
WHERE Id NOT IN (SELECT ProductId FROM Orders)
Merită de menționat că aceasta nu este cea mai eficientă modalitate de a extrage date legate de alte tabele, deoarece pentru consolidarea datelor din tabele diferite se poate utiliza operatorul JOIN, care este abordat în capitolul următor.
Obținerea unui set de valori
Atunci când subinterogările sunt folosite în operații de comparație, ar trebui să returneze o singură valoare scalară. Cu toate acestea, uneori există nevoia de a obține un set de valori. Pentru a permite subinterogării să returneze un set de valori în operațiile de comparație, este necesar să se utilizeze unul dintre operatorii: ALL, SOME sau ANY.
Atunci când se utilizează cuvântul cheie ALL, condiția în operația de comparație trebuie să fie adevărată pentru toate valorile returnate de subinterogare. De exemplu, să găsim toate produsele al căror preț este mai mic decât cel al oricărui produs Apple:
SELECT * FROM Products
WHERE Price < ALL(SELECT Price FROM Products WHERE Manufacturer='Apple')
Dacă am omite cuvântul cheie ALL în acest caz, ne-am confrunta cu o eroare.
Să presupunem că subinterogarea dată returnează valorile val1, val2 și val3. Atunci condiția de filtrare ar fi echivalentă cu combinarea acestor valori prin operatorul AND:
WHERE Price < val1 AND Price < val2 AND Price < val3
În același timp, o astfel de interogare poate fi rescrisă mult mai simplu în alt mod:
SELECT * FROM Products
WHERE Price < (SELECT MIN(Price) FROM Products WHERE Manufacturer='Apple')
Cum funcționează operatorul ALL:
- x > ALL (1, 2) este echivalent cu x > 2
- x < ALL (1, 2) este echivalent cu x < 1
- x = ALL (1, 2) este echivalent cu (x = 1) AND (x = 2)
- x <> ALL (1, 2) este echivalent cu x NOT IN (1, 2)
Operatorii ANY și SOME necesită ca condiția din operația de comparație să fie adevărată pentru cel puțin una dintre valorile returnate de subinterogare. Acești doi operatori au aceeași funcționalitate, astfel încât puteți utiliza oricare dintre ei.
De exemplu, în următorul caz vom obține produsele care costă mai puțin decât cel mai scump produs al companiei Apple:
SELECT * FROM Products
WHERE Price < ANY(SELECT Price FROM Products WHERE Manufacturer='Apple')
Și merită să menționăm că această interogare poate fi simplificată, rescriind-o astfel:
SELECT * FROM Products
WHERE Price < (SELECT MAX(Price) FROM Products WHERE Manufacturer='Apple')
Cum funcționează operatorul ANY (și de asemenea SOME):
- x > ANY (1, 2) este echivalent cu x > 1
- x < ANY (1, 2) este echivalent cu x < 2
- x = ANY (1, 2) este echivalent cu x IN (1, 2)
- x <> ANY (1, 2) este echivalent cu (x <> 1) OR (x <> 2)
Subinterogarea ca specificație de coloană
Rezultatul unei subinterogări poate reprezenta o coloană separată în selecție. De exemplu, să selectăm toate comenzile și să adăugăm informații despre numele produsului:
SELECT *,
(SELECT ProductName FROM Products WHERE Id=Orders.ProductId) AS Product
FROM Orders

Subinterogările în comanda INSERT pot fi utilizate pentru a determina valoarea care este introdusă într-una dintre coloane:
INSERT INTO Orders (ProductId, CreatedAt, ProductCount, Price)
VALUES
(
(SELECT Id FROM Products WHERE ProductName='Galaxy S8'),
'2018-05-23',
2,
(SELECT Price FROM Products WHERE ProductName='Galaxy S8')
)
Subinterogările în comanda UPDATE pot fi utilizate:
- Ca valoare de actualizat după operatorul SET
- Ca parte a condiției în clauza WHERE
Astfel, vom mări în tabela Orders cantitatea de produse cumpărate de la compania Apple cu 2:
UPDATE Orders
SET ProductCount = ProductCount + 2
WHERE ProductId IN (SELECT Id FROM Products WHERE Manufacturer='Apple');
Sau vom seta prețul produsului pentru comanda primită ca rezultat al unei subinterogări:
UPDATE Orders
SET Price = (SELECT Price FROM Products WHERE Id=Orders.ProductId) + 3000
WHERE Id=1;
Subinterogările în comanda DELETE
Subinterogările în comanda DELETE sunt utilizate și ele ca parte a condiției. Astfel, vom șterge toate comenzile pentru Galaxy S8.
DELETE FROM Orders
WHERE ProductId=(SELECT Id FROM Products WHERE ProductName='Galaxy S8');