Cea mai complexă, dar în același timp și cea mai interesantă temă sunt subcotările. Acest lucru este destul de un puternic mijloc de obținere a datelor necesare, iar pe de altă parte, acest instrument este foarte mult un efort pe serverul de interogare de performanță de procesare. În primul rând, învățăm să lucrăm cu subinterogările, deoarece acestea pot fi folosite pentru a rezolva rapid problema, iar apoi vom învăța să scape de subinterogările, care este identic cu optimizarea.
Această sarcină poate fi rezolvată cu ușurință folosind subcheiri:
În acest exemplu, selectăm toate intrările din tabelul tbPhoneNumbers. În acest caz, câmpul "idPhoneType" este comparat cu rezultatul subchetei, care este scris în paranteze. Deoarece există un semn egal, rezultatul subcotării trebuie să fie dintr-un câmp și dintr-un rând. Dacă rezultatul este de două câmpuri sau mai mult de o linie, atunci serverul va returna o eroare.
Încercați următoarea interogare:
Această interogare va returna două rânduri cu două valori cheie cheie. Ca răspuns la aceasta, serverul returnează o eroare:
Anumite obiecte au returnat mai mult de o valoare. Acest lucru nu este permis atunci când subcheierea urmează =. = <, <=. &qt;, &qt;= or when the subquery is used as an expression.
(Subchetul returnează mai mult de o valoare. Aceasta nu este permisă atunci când subchetul urmărește valoarea =. =, <, <=. &qt;, &qt;= или когда подзапрос используется как выражение)
Și apoi ce pot folosi? Dacă credeți puțin, atunci pentru o astfel de interogare, semnul de egalitate ar trebui înlocuit cu instrucțiunea IN:
Mai întâi, SQL va executa interogarea internă, care este localizată în paranteze, iar rezultatul va fi înlocuit în interogarea externă.
Am deja sugerat că rezultatul subcotării ar trebui să fie format dintr-o singură coloană. Aceasta înseamnă că nu puteți scrie în interogarea internă SELECT *, dar puteți selecta numai câmpul SELECT. Rețineți că numele trebuie să fie doar unul și tipul trebuie să se potrivească cu tipul valorii comparate. Subqueries trebuie să fie utilizate foarte atent, deoarece acestea pot duce la o eroare.
Este foarte important ca subcheierea să fie în paranteze și în dreapta semnului egal. Standardul nu vă permite să scrieți subqueries în stânga. Aceasta înseamnă că următoarea interogare nu este validă:
În acest exemplu, subcheierea este mai întâi urmată de un semn egal, și numai atunci este domeniul cu care doriți să comparați.
Interogarea principală (denumită și externă) poate accesa o subchetare (interogare internă). Pentru aceasta, trebuie să specificați aliasuri pentru tabele. Să analizăm următoarea interogare:
Observați penultima linie:
Aici comparăm "vcPhoneNumber" din tabelul ot cu șablonul. Cel mai interesant lucru este că ot - alias tbPhoneNumbers de masă, care este descrisă în secțiunea de la cererea externă. Însă, în ciuda acestui fapt, putem să facem referire din subcvariu prin alias la coloanele de interogări externe. Astfel, este posibilă direcționarea unor conexiuni destul de complexe între cereri.
O astfel de interogare va fi executată folosind următorul algoritm:
- Selectați un rând din tabelul tbPhoneNumbers din interogarea externă. Acesta va fi șirul candidat curent.
- Salvați valorile din acest șir de candidați într-un alias numit ot.
- Efectuați o subchetare, în timp ce o interogare externă participă și în timpul căutării.
- Evaluați "idPhoneType" a interogării externe pe baza rezultatelor subchetei executate în etapa anterioară. Aceasta determină dacă șirul candidat este selectat pentru ieșire pe ecran.
Subqueries pot fi nu numai în clauza WHERE, dar și în secțiunea SELECT și în clauza FROM. Să aruncăm o privire mai întâi la sub-cererile din FROM, pentru care am pus o sarcină destul de complicată, dar interesantă. În timpul grupării am putut afla cum să determinăm numărul de utilizatori cu numele Andrew. Și dacă creați un tabel care va conține trei coloane:
Sub forma a două întrebări, această problemă este rezolvată destul de simplu. Următoarea interogare determină numărul fiecărui nume din tabel:
Am examinat deja această solicitare.
Avem două mese diferite. Și cum să le unim acum într-un singur întreg? Încearcă să rezolvi singuri această sarcină. Soluția mea poate fi văzută în lista 2.3.
În clauza FROM, în loc de a specifica tabele, interogările de mai sus sunt închise în paranteze. Se specifică un alias pentru fiecare solicitare, altfel este imposibil să lucrați cu câmpurile de interogare. Se pare că, în loc de a obține date direct de pe masă, le obținem din interogare.
Pentru astfel de solicitări, există o singură restricție - fiecare câmp din subdotarea secțiunii FROM trebuie să aibă un nume. Avem câmpuri care numără numărul de înregistrări și pentru că nu există astfel de câmpuri, numele nu este setat, așa că am setat pseudonime. În prima subcâmplare, coloana cu numărul de înregistrări este numită PeopleNumber, iar în cea de-a doua subchetare, PhoneNum.
Legături externe unind atât a primit o solicitare prin câmpul nume de tabel „vcName“, iar rezultatul este o masă generală (a se vedea figura 2.7 ..), care este format din patru coloane - denumirea și cantitatea primei cereri, precum și numele și numărul de a doua solicitare. Una dintre coloanele de nume poate fi eliminată, deoarece acestea sunt identice, dar am decis să plec pentru a putea vedea conexiunea.
Rezultatul combinării a două mese
În secțiunea SELECT, vom interoga mai întâi toate coloanele din tabelul tbPeople (pl. *). Apoi, în loc de următorul câmp în paranteze, este specificată o subchetare care selectează datele. Astfel, într-o subcotare în secțiunea WHERE a fi cauzată comunicarea între mese. Se pare că putem accesa, de asemenea, câmpuri de solicitare externă din acest subproiect.
Singura restricție este că subcheierea din secțiunea SELECT trebuie să returneze doar un rând. Dacă rezultatul este mai multe linii, interogarea returnează o eroare.
Toate exemplele pe care le-am discutat mai sus sunt destul de simple pentru a le pune în aplicare, fără a folosi subcotări. De exemplu, consultați următoarea interogare:
Aceeași problemă este rezolvată după cum urmează:
Legați pur și simplu ambele mese și specificați aceeași condiție. Astfel, am scăpat de subdotare, iar acum serverul poate îndeplini sarcina mai repede. Cele mai multe sarcini pot fi rezolvate fără subcotări, dacă legați corect tabelele. De aceea, în această carte, voi încerca să folosesc cât mai puțin subunități și vom încerca să rezolvăm totul cu o singură instrucțiune SELECT.
Dar următoarea interogare este destul de greu de făcut fără subtraveriile. Să presupunem că trebuie să determinați datele din ultimul rând adăugat în tabel. Dacă cheia primară este utilizată pentru a mărește automat domeniu, este necesar să se cunoască cea mai mare valoare cheie primară folosind operatorul MAX, și apoi găsi o linie cu această cheie. Iată cum este definită ultima linie din tabelul tbPeoples:
O astfel de interogare ne va ajuta mult atunci când vom învăța să adăugăm înregistrări la masă, astfel încât să puteți vedea rapid rezultatul lucrării.