Lecții din modul (4/4)
Grupuri de filtrare: HAVING
Odată ce aveți un rezultat pe grup (lecția anterioară), de multe ori doriți
pastreaza doar grupele care indeplinesc o conditie: departamente cu mai multe
peste 2 persoane, proiecte cu un buget mediu peste 100k, utilizatori cu
minim 10 comenzi. Pentru a face acest lucru WHERE nu este suficient.
De ce UNDE nu este suficient
WHERE filtrează rândurile de tabel, înainte de agregare. Deci nu poate vedea
rezultatul COUNT(*) sau AVG(...): până la rularea WHERE, cei
valorile nu au fost încă calculate.
-- ERROR: COUNT(*) doesn't exist yet when WHERE is evaluated
SELECT department_id, COUNT(*) AS count
FROM employees
WHERE COUNT(*) > 2 -- ❌ doesn't work
GROUP BY department_id;Pentru a filtra după agregare există o clauză dedicată: HAVING.
Sintaxa
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM table
GROUP BY grouping_column
HAVING condition_on_aggregate;-- Departments with more than 2 employees:
SELECT department_id, COUNT(*) AS count
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 2;HAVING este să GROUP BY ceea ce WHERE este să FROM: aceeași idee
(„filtru”), dar aplicat după grupare, pe ansamblu.
Ordinea logică a clauzelor
Pentru a nu confunda niciodată WHERE și HAVING, amintiți-vă ordinea în care
SQL le execută mental:
FROM/JOIN— construiește tabelul de pornire prin alăturarea surselor.WHERE— renunță la rândurile care nu vă interesează.GROUP BY— colectează rândurile rămase în grupuri.HAVING— elimină grupurile de care nu vă interesează.SELECT— calculează coloanele finale (inclusiv agregatele).ORDER BY/LIMIT— reordonați și tăiați.
Note importante:
- în
WHEREpoți folosi doar coloane de tabel; - în
HAVINGputeți folosi gruparea coloanelor și agregatelor.
-- Classic combo: filter first, group, filter the groups, sort.
SELECT d.name, AVG(e.salary) AS average
FROM employees AS e
JOIN departments AS d ON e.department_id = d.id
WHERE e.hired_on >= '2018-01-01' -- filter rows
GROUP BY d.name
HAVING AVG(e.salary) > 35000 -- filter groups
ORDER BY average DESC;Încearcă
Pentru fiecare departament, arătați numele (departments.name) și numărul de angajați, DAR numai pentru departamentele cu cel puțin 2 angajați. Două coloane, un rând pentru fiecare departament calificat.
Afișează indiciu
Condiția „cel puțin 2” devine COUNT(*) >= 2 în HAVING.
Soluție disponibilă după 3 încercări
Exercițiu de revizuire
Afișați departamentele (departamente.nume) al căror salariu mediu depășește 35000. Luați în considerare doar angajații angajați din 2018 încolo. Două coloane: nume și media. Sortați după medie descrescătoare.
Afișează indiciu
WHERE filtrează rândurile (angajați angajați din 2018), HAVING filtrează grupurile (medie > 35000).
Soluție disponibilă după 3 încercări