TOP

SQL-Lecția 11. Combinație avansată de tabele (OUTER JOIN)

În secțiunea anterioară, am luat în considerare cele mai simple moduri de a combina tabele - folosind propoziții WHERE și INNER JOIN. Aceste combinații se numesc combinații interne sau combinații de echivalență. Cu toate acestea, SQL are în arsenalul său mult mai multe opțiuni pentru alăturarea tabelelor, și anume, există și alte tipuri de îmbinări: îmbinări exterioare, îmbinări naturale și self-joins. Dar mai întâi, să luăm în considerare modul în care putem atribui alias-uri tabelelor, deoarece mai târziu vom fi forțați să folosim nume complete ale câmpurilor (Table.Field), care fără abrevieri vor fi foarte greu de utilizat din cauza lungimii lor mari.


1. Utilizarea aliasurilor de tabel (Aliases)

În secțiunea anterioară, am învățat cum pot fi folosite aliasurile pentru a face referire la anumite câmpuri de tabel sau câmpuri calculate. De asemenea, SQL ne permite să folosim aliasuri în loc de nume de tabel. Acest lucru ne oferă avantaje, cum ar fi o sintaxă SQL mai scurtă și ne permite să folosim același tabel de mai multe ori în instrucțiunea SELECT.

Run SQLSELECT Seller_name, SUM(Amount) AS Sum1 
FROM Sellers AS S, Sumproduct AS SP 
WHERE S.City = SP.City 
GROUP BY Seller_name

Am afișat cantitatea totală de bunuri vândute pentru fiecare vânzător. În interogarea noastră SQL, am folosit următoarele alias-uri: pentru câmpul calculat SUM(Amount) alias-ul Sum1, pentru tabelul Sellers alias-ul S și pentru Sumproduct alias-ul SP. Rețineți că aliasurile de tabel pot fi folosite și în alte propoziții, cum ar fi ORDER BY, GROUP BY și altele.

2. Autoconectare (SELF JOIN)

Să luăm în considerare un exemplu. Să presupunem că trebuie să știm adresa vânzătorilor care fac comerț în aceeași țară cu John Smith. Pentru a face acest lucru, vom crea următoarea solicitare:

Run SQLSELECT Address, City, Country, Seller_name
FROM Sellers
WHERE Country = (SELECT Country 
                 FROM Sellers 
                 WHERE Seller_name = 'John Smith')

De asemenea, putem rezolva această problemă prin autoconectare scriind următorul cod:

Run SQLSELECT S1.Address, S1.City, S1.Country, S1.Seller_name
FROM Sellers AS S1, Sellers AS S2 
WHERE S1.Country = S2.Country AND S2.Seller_name = 'John Smith'

Pentru a rezolva această problemă au fost folosite pseudonime. Prima dată tabelului Sellers i s-a atribuit aliasul S1, a doua oară - aliasul S2. Aceste alias-uri pot fi apoi folosite ca nume de tabel. În operatorul WHERE, adăugăm prefixul S1 la numele fiecărui câmp, astfel încât DBMS să înțeleagă câmpurile din care tabel ar trebui să fie scos (deoarece am făcut două tabele virtuale dintr-un tabel). Clauza WHERE unește mai întâi tabelele și apoi filtrează datele celui de-al doilea tabel după câmpul Seller_name pentru a returna doar valorile necesare.

Auto-asocierile sunt adesea folosite pentru a înlocui subinterogările care selectează date din același tabel cu operatorul exterior SELECT. Deși rezultatul final este același, multe procese SGBD-uri se alătură mult mai rapid decât subinterogările. Merită să experimentați pentru a determina care interogare funcționează mai rapid.

3. Combinație naturală

O îmbinare naturală este o îmbinare în care selectați numai acele coloane care nu se repetă. Acest lucru se face de obicei prin scrierea (SELECT *) pentru un tabel și specificând o listă de câmpuri pentru restul tabelelor. Exemplu:

Run SQLSELECT SP.*, S.Country
FROM Sumproduct AS SP, Sellers AS S 
WHERE SP.City = S.City

În acest exemplu, wildcard (*) este folosit numai pentru primul tabel. Toate celelalte coloane sunt specificate în mod explicit, astfel încât coloanele duplicat nu sunt selectate.

4. Combinație externă (OUTER JOIN)

De obicei, la îmbinare, rândurile unui tabel sunt conectate cu rândurile corespunzătoare ale altui tabel, totuși, în unele cazuri, poate fi necesar să se includă în rezultat rânduri care nu au rânduri înrudite într-un alt tabel (adică toate sunt selectate rânduri dintr-un tabel și se adaugă numai linii aferente din altul). O conexiune de acest tip se numește externă. Pentru aceasta se folosesc cuvintele cheie OUTER JOIN ... ON ... cu prefixul LEFT sau RIGHT.

Să luăm în considerare un exemplu, după ce a adăugat anterior un nou vânzător - Semuel Piter, care nu are încă vânzări, la tabelul Sellers:

Run SQLSELECT Seller_name, SUM(Quantity) AS Qty
FROM Sellers2 
LEFT OUTER JOIN Sumproduct 
ON Sellers2.City = Sumproduct.City
GROUP BY Seller_name

Cu această solicitare, am extras lista tuturor vânzătorilor din baza de date și am calculat cantitatea totală de mărfuri vândute pentru aceștia pentru toate lunile. Vedem că nu există vânzări pentru noul vânzător Semuel Piter. Dacă am folosi o îmbinare internă, atunci nu am vedea noul vânzător, deoarece nu are înregistrări în tabelul Sumproduct. De asemenea, putem schimba direcția combinației nu numai prin scriere LEFT sau RIGHT, dar și prin simpla schimbare a ordinii tabelelor (adică următoarele două înregistrări vor da același rezultat: Sellers LEFT OUTER JOIN SumproducttbltblTblt Sumproducttbltblt _producttbltbltblt _produs JOIN Sellers).

De asemenea, unele SGBD-uri permit îmbinări externe pe o înregistrare simplificată folosind semnele *= și =*, care corespund cu LEFT OUTER JOIN și, respectiv, RIGHT OUTER JOIN. Astfel, interogarea anterioară ar putea fi rescrisă după cum urmează:

SELECT Seller_name, SUM(Quantity) AS Qty
FROM Sellers, Sumproduct
WHERE Sellers.City *= Sumproduct.City

Din păcate, MS Access nu acceptă o înregistrare scurtată pentru o îmbinare exterioară.

5. Îmbinare completă externă (FULL OUTER JOIN)

Există, de asemenea, un alt tip de îmbinare exterioară - o îmbinare exterioară completă, care afișează toate rândurile din ambele tabele și le unește numai pe cele care pot fi legate. Sintaxa unei îmbinări externe complete este următoarea:

SELECT Seller_name, Product
FROM Sellers 
FULL OUTER JOIN Sumproduct 
ON Sellers.City = Sumproduct.City

Din nou, îmbinarea exterioară completă nu este acceptată de următorul SGBD: MS Access, MySQL, SQL Server și Sybase. Cum să ocolim această nedreptate, vom lua în considerare în secțiunea următoare.