Lezioni del modulo (3/4)
Raggruppare con GROUP BY
Nel Modulo 2 hai imparato che COUNT(*), AVG(...), SUM(...) riducono
tutte le righe a una sola riga di risultato. Ma cosa succede se vuoi una
media stipendio per ogni dipartimento, non per l'intera azienda? Vuoi
una riga per ogni gruppo. È il lavoro di GROUP BY.
La sintassi
SELECT colonna_di_raggruppamento, FUNZIONE_AGGREGATA(...)
FROM tabella
GROUP BY colonna_di_raggruppamento;Letta in italiano: "dividi le righe in gruppi che hanno lo stesso valore di
colonna_di_raggruppamento, e per ogni gruppo calcola l'aggregato".
-- Stipendio medio per dipartimento:
SELECT department_id, AVG(salary) AS average
FROM employees
GROUP BY department_id;Il risultato ha una riga per ogni department_id distinto trovato in
employees. Otterrai 5 righe: una per ciascuno dei 4 dipartimenti (1, 2,
3, 4) più una per NULL (Andrea Costa).
Con JOIN per nomi leggibili
Spesso vuoi raggruppare per department_id ma mostrare il nome del
dipartimento. Si combina GROUP BY con 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;Questa è una query di business intelligence in piena regola: in tre righe ti dice quanti dipendenti ha ogni dipartimento e quanto guadagnano in media, ordinati dal più grande al più piccolo.
La regola d'oro
Quando usi GROUP BY, ogni colonna nella SELECT deve essere:
- una delle colonne di raggruppamento (es.
department_id,d.name), o - dentro una funzione di aggregazione (es.
AVG(salary),COUNT(*)).
-- ERRORE: first_name non è né nel GROUP BY né dentro un aggregato
SELECT department_id, first_name, AVG(salary)
FROM employees
GROUP BY department_id;PostgreSQL ti restituisce un errore esplicito ("column must appear in the
GROUP BY clause or be used in an aggregate function"). È un errore comune
delle prime settimane: se lo vedi, fermati e chiediti "qual è il valore di
first_name per un gruppo di 3 persone?" — non c'è una risposta singola, ed
è per questo che il motore si rifiuta.
Prova tu
Per ogni dipartimento, calcola quanti dipendenti contiene. Restituisci due colonne: il nome del dipartimento (departments.name) e il conteggio dei dipendenti. Una riga per dipartimento.
Mostra suggerimento
Aggrega con COUNT(*) e raggruppa per d.name. La SELECT deve contenere solo la colonna di raggruppamento e l'aggregato.
Soluzione disponibile dopo 3 tentativi
Esercizio di ripasso
Per ogni dipartimento (departments.name), calcola lo stipendio medio (AVG(salary)) dei suoi dipendenti, ordinato dal più alto al più basso.
Mostra suggerimento
AVG(e.salary) come aggregato, GROUP BY d.name, ORDER BY average DESC.
Soluzione disponibile dopo 3 tentativi