SQL Order of Operations – În ce ordine execută MySQL interogările?
Click pentru a începe, gratuit.
Cunoașterea biților și octeților din ordinea operațiilor unei interogări SQL poate fi foarte valoroasă, deoarece poate ușura procesul de scriere a unor noi interogări, fiind în același timp foarte benefică atunci când se încearcă optimizarea unei interogări SQL.
Dacă sunteți în căutarea unei versiuni scurte, aceasta este ordinea logică a operațiilor, cunoscută și sub numele de ordinea de execuție, pentru o interogare SQL:
- DE LA, inclusiv funcțiile JOIN
- WHERE
- GROUP BY
- HAVING
- WINDOW
- SELECT
- DISTINCT
- UNION
- ORDER BY
- LIMIT și OFFSET
.
Dar realitatea nu este atât de ușoară și nici atât de directă. Așa cum am spus, standardul SQL definește ordinea de execuție pentru diferitele clauze de interogare SQL. Acestea fiind spuse, bazele de date moderne sfidează deja această ordine implicită prin aplicarea unor trucuri de optimizare care ar putea schimba ordinea reală de execuție, deși trebuie să sfârșească prin a returna același rezultat ca și cum ar fi rulat interogarea în ordinea de execuție implicită.
De ce ar face asta? Ei bine, poate fi o prostie dacă baza de date ar prelua mai întâi toate datele menționate în clauza FROM (inclusiv JOIN-urile), înainte de a se uita în clauza WHERE și în indicii acesteia. Aceste tabele pot conține o mulțime de date, așa că vă puteți imagina ce se va întâmpla dacă optimizatorul bazei de date ar respecta ordinea tradițională a operațiilor unei interogări SQL.
Să analizăm fiecare dintre părțile interogării SQL în funcție de ordinea lor de execuție.
FROM și JOINs
Tabelele specificate în clauza FROM (inclusiv JOINs), vor fi evaluate mai întâi, pentru a determina întregul set de lucru care este relevant pentru interogare. Baza de date va fuziona datele din toate tabelele, în conformitate cu clauzele JOINs ON, în timp ce va prelua, de asemenea, datele din subinterogări și ar putea chiar crea unele tabele temporare pentru a păstra datele returnate din subinterogările din această clauză.
În multe cazuri, totuși, optimizatorul bazei de date va alege să evalueze mai întâi partea WHERE, pentru a vedea ce parte a setului de lucru poate fi lăsată deoparte (de preferință folosind indici), astfel încât să nu umfle prea mult setul de date dacă nu este cu adevărat necesar.
Clauza WHERE
Clauza WHERE va fi a doua care va fi evaluată, după clauza FROM. Avem setul de date de lucru, iar acum putem filtra datele în funcție de condițiile din clauza WHERE.
Aceste condiții pot include referințe la datele și tabelele din clauza FROM, dar nu pot include referințe la pseudonimele definite în clauza SELECT, deoarece este posibil ca acele date și acele pseudonime să nu „existe” încă în acel context, deoarece acea clauză nu a fost încă evaluată de baza de date.
De asemenea, o capcană comună pentru clauza WHERE ar fi încercarea de a filtra valorile agregate în clauza WHERE, de exemplu cu această clauză: „WHERE sum(available_stock) > 0”. Această declarație va eșua în executarea interogării, deoarece agregările vor fi evaluate mai târziu în cadrul procesului (a se vedea secțiunea GROUP BY de mai jos). Pentru a aplica o condiție de filtrare asupra datelor agregate, trebuie să utilizați clauza HAVING și nu clauza WHERE.
Clauza GROUP BY
Acum că am filtrat setul de date utilizând clauza WHERE, putem agrega datele în funcție de una sau mai multe coloane care apar în clauza GROUP BY. Gruparea datelor înseamnă, de fapt, împărțirea lor în diferite bucăți sau găleți, unde fiecare găleată are o cheie și o listă de rânduri care corespund acelei chei. Neavând o clauză GROUP BY este ca și cum ați pune toate rândurile într-o singură găleată imensă.
După ce ați agregat datele, puteți utiliza acum funcții de agregare pentru a returna o valoare per grup pentru fiecare dintre găleți. Astfel de funcții de agregare includ COUNT, MIN, MAX, SUM și altele.
Clauza HAVING
Acum că am grupat datele cu ajutorul clauzei GROUP BY, putem folosi clauza HAVING pentru a filtra unele găleți. Condițiile din clauza HAVING se pot referi la funcțiile de agregare, astfel încât exemplul care nu a funcționat în clauza WHERE de mai sus, va funcționa foarte bine în clauza HAVING: „HAVING sum(available_stock) > 0”.
Deoarece am grupat deja datele, nu mai putem accesa rândurile originale în acest moment, astfel încât putem aplica doar condiții pentru a filtra găleți întregi, și nu rânduri individuale dintr-o găleată.
De asemenea, așa cum am menționat în secțiunile anterioare, nici aliasurile definite în clauza SELECT nu pot fi accesate în această secțiune, deoarece nu au fost încă evaluate de baza de date (acest lucru este valabil în majoritatea bazelor de date).
Funcții de fereastră
Dacă folosiți funcții de fereastră, acesta este punctul în care acestea vor fi executate. La fel ca și mecanismul de grupare, funcțiile Window efectuează, de asemenea, un calcul asupra unui set de rânduri. Principala diferență este că, atunci când se utilizează funcțiile Window, fiecare rând își va păstra propria identitate și nu va fi grupat într-o găleată de alte rânduri similare.
Funcțiile Window pot fi utilizate numai în clauza SELECT sau ORDER BY. Puteți utiliza funcții de agregare în interiorul funcțiilor Window, de exemplu:
SUM(COUNT(*)) OVER ()
Clauza SELECT
Acum că am terminat de eliminat rândurile din setul de date și de grupat datele, putem selecta datele pe care dorim să fie preluate din interogare în partea clientului. Puteți utiliza nume de coloane, agregări și subsecvențe în cadrul clauzei SELECT. Rețineți că, dacă utilizați o referință la o funcție de agregare, cum ar fi COUNT(*) în clauza SELECT, aceasta este doar o referință la o agregare care a avut deja loc atunci când a avut loc gruparea, astfel încât agregarea în sine nu are loc în clauza SELECT, ci este doar o referință la setul său de rezultate.
Cuvântul cheie DISTINCT
Sintaxa cuvântului cheie DISTINCT este un pic confuză, deoarece cuvântul cheie își ocupă locul înaintea numelor de coloane în clauza SELECT. Dar, operațiunea DISTINCT propriu-zisă are loc după SELECT. Atunci când se utilizează cuvântul cheie DISTINCT, baza de date va elimina rândurile cu valori duplicate din rândurile rămase după ce au avut loc filtrarea și agregările.
Cuvântul cheie UNION
Cuvântul cheie UNION combină seturile de rezultate a două interogări într-un singur set de rezultate. Majoritatea bazelor de date vă vor permite să alegeți între UNION DISTINCT (care va elimina rândurile duplicate din setul de rezultate combinat) sau UNION ALL (care doar combină seturile de rezultate fără a aplica nicio verificare a dublării).
Puteți aplica sortarea (ORDER BY) și limitarea (LIMIT) asupra setului de rezultate al UNION, în același mod în care le puteți aplica la o interogare obișnuită.
Clauza ORDER BY
Sortarea are loc odată ce baza de date are întregul set de rezultate pregătit (după filtrare, grupare, eliminarea dublărilor). Odată ce avem acest lucru, baza de date poate acum să sorteze setul de rezultate folosind coloane, aliasuri selectate sau funcții de agregare, chiar dacă acestea nu fac parte din datele selectate. Singura excepție este atunci când se folosește cuvântul cheie DISTINCT, care împiedică sortarea în funcție de o coloană neselectată, deoarece în acest caz ordinea setului de rezultate va fi nedefinită.
Puteți alege să sortați datele folosind o ordine descrescătoare (DESC) sau o ordine ascendentă (ASC). Ordinea poate fi unică pentru fiecare dintre părțile de ordine, astfel încât este valabilă următoarea formulă: ORDER BY firstname ASC, age DESC
LIMIT și OFFSET
În majoritatea cazurilor de utilizare (cu excepția câtorva, cum ar fi raportarea), am dori să eliminăm toate rândurile, cu excepția primelor X rânduri din rezultatul interogării. Clauza LIMIT, care se execută după sortare, ne permite să facem exact acest lucru. În plus, puteți alege de la ce rând să începeți să preluați datele și câte rânduri să excludeți, folosind o combinație a cuvintelor cheie LIMIT și OFFSET. Următorul exemplu va prelua 50 de rânduri începând cu rândul #100: LIMIT 50 OFFSET 100
Click pentru a începe, gratuit.