Lecții din modul (3/4)
Gruparea cu GROUP BY
În modulul 2 ați învățat că COUNT(*), AVG(...), SUM(...) reduc toate
rânduri la un un singur rând de rezultat. Dar dacă vrei un salariu mediu
pentru fiecare departament, nu pentru întreaga companie? Vrei un rând per
grup. Aceasta este treaba lui GROUP BY.
Sintaxa
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM table
GROUP BY grouping_column;Citiți în engleză: "împărțiți rândurile în grupuri care au aceeași valoare a
grouping_column, iar pentru fiecare grup calculați agregatul".
-- Average salary per department:
SELECT department_id, AVG(salary) AS average
FROM employees
GROUP BY department_id;Rezultatul are un rând pentru fiecare department_id distinct găsit în
employees. Veți primi 5 rânduri: unul pentru fiecare dintre cele 4 departamente (1, 2,
3, 4) plus unul pentru NULL (Andrea Costa).
Cu JOIN pentru nume care pot fi citite
Deseori doriți să grupați după department_id, dar afișați numele
departament. Combinați GROUP BY cu un JOIN:
SELECT d.name AS department,
COUNT(*) AS count,
AVG(e.salary) AS average_salary
FROM employees AS e
JOIN departments AS d ON e.department_id = d.id
GROUP BY d.name
ORDER BY count DESC;Aceasta este o interogare completă de business intelligence: în trei rânduri vă spune câți angajați are fiecare departament și cu cât câștigă medie, sortate de la cel mai mare la cel mai mic.
Regula de aur
Când utilizați GROUP BY, fiecare coloană din SELECT trebuie să fie:
- una dintre coloanele de grupare (de exemplu,
department_id,d.name) sau - în interiorul unei funcții agregate (de exemplu,
AVG(salary),COUNT(*)).
-- ERROR: first_name is neither in GROUP BY nor inside an aggregate
SELECT department_id, first_name, AVG(salary)
FROM employees
GROUP BY department_id;PostgreSQL returnează o eroare explicită (coloana "trebuie să apară în GROUP BY
clauză sau să fie utilizat într-o funcție agregată"). Este o săptămână de început obișnuită
greșeală: dacă o vezi, oprește-te și întreabă-te "care este valoarea
first_name pentru un grup de 3 persoane?" — nu există un singur răspuns și
de aceea motorul refuza.
Încearcă
Pentru fiecare departament, calculați câți angajați conține. Returnează două coloane: numele departamentului (departments.name) și numărul de angajați. Un rând pe departament.
Afișează indiciu
Agregați cu COUNT(*) și grupați după d.nume. SELECT trebuie să conțină numai coloana de grupare și agregatul.
Soluție disponibilă după 3 încercări
Exercițiu de revizuire
Pentru fiecare departament (departments.name), calculați salariul mediu (AVG(salariu)) al angajaților săi, sortați de la cel mai mare la cel mai mic.
Afișează indiciu
AVG(e.salary) ca agregat, GROUP BY d.name, ORDER BY medie DESC.
Soluție disponibilă după 3 încercări