MySQL — Funzioni Aggregate

COUNT · SUM · AVG · GROUP BY · HAVING · MySQL 9.7 LTS · Marco Consiglio
Volta Institute · Napoli
A.A. 2026
🔢 COUNT() — contare le righe
Le funzioni aggregate condensano molte righe in un unico valore riassuntivo — lo stesso concetto di reduce() visto in PHP/JavaScript, ma eseguito direttamente dal motore del database, spesso molto più efficiente.
SELECT COUNT(*) FROM studenti; -- restituisce il numero totale di righe nella tabella SELECT COUNT(*) FROM studenti WHERE voto >= 18; -- conta solo gli studenti promossi
COUNT(*)
24
💡 COUNT(*) conta tutte le righe indipendentemente dai valori; COUNT(colonna) conta solo le righe dove quella colonna specifica NON è NULL — una distinzione importante da ricordare.
➕ SUM() — sommare valori numerici
SELECT SUM(prezzo) FROM ordini; -- somma tutti i valori della colonna prezzo, restituendo un unico totale
💡 Concettualmente identico ad array_sum() in PHP o .reduce((a,b)=>a+b) in JavaScript — ma eseguito interamente dal database, senza dover scaricare tutte le righe per sommarle manualmente nel codice applicativo.
📐 AVG() — calcolare la media
SELECT AVG(voto) FROM studenti; -- restituisce la media aritmetica di tutti i voti
AVG(voto)
24.6667
✅ AVG() calcola automaticamente somma e divisione — non serve chiamare separatamente SUM() e COUNT() per poi dividere manualmente, anche se il risultato sarebbe matematicamente equivalente.
📊 MIN() e MAX() — valori estremi
SELECT MIN(voto) AS voto_minimo, MAX(voto) AS voto_massimo FROM studenti;
voto_minimovoto_massimo
1530
💡 AS qui rinomina la colonna del risultato (alias di colonna, diverso dall'alias di tabella visto nella guida sui JOIN) — utile per rendere leggibile l'output quando la funzione aggregata da sola produrrebbe un nome di colonna poco chiaro come "MIN(voto)".
🗂️ GROUP BY — aggregare per categorie
GROUP BY raggruppa le righe che condividono lo stesso valore in una colonna, permettendo di applicare le funzioni aggregate separatamente per ciascun gruppo, invece che sull'intera tabella.
SELECT corso, COUNT(*) AS num_studenti FROM iscrizioni GROUP BY corso;
corsonum_studenti
Full Stack12
Contabilità8
Marketing4
⚠️ Regola fondamentale: ogni colonna nella SELECT deve essere o dentro GROUP BY o dentro una funzione aggregata — scrivere SELECT corso, nome, COUNT(*) ... GROUP BY corso (con nome non aggregato né raggruppato) genera un errore o un risultato ambiguo.
📈 GROUP BY con AVG — media per gruppo
SELECT corso, AVG(voto) AS media_voto FROM iscrizioni GROUP BY corso ORDER BY media_voto DESC; -- media voti per ciascun corso, dal più alto al più basso
🎯 HAVING vs WHERE — filtrare PRIMA o DOPO l'aggregazione
Questa è la distinzione più confusa per chi inizia con SQL: WHERE filtra le righe prima del raggruppamento; HAVING filtra i gruppi dopo che l'aggregazione è stata calcolata.
SELECT corso, COUNT(*) AS num_studenti FROM iscrizioni GROUP BY corso HAVING COUNT(*) > 5; -- mostra solo i corsi con PIÙ di 5 studenti iscritti (filtro sul GRUPPO, dopo il conteggio)
⚠️ Errore comune: scrivere WHERE COUNT(*) > 5 invece di HAVING COUNT(*) > 5 genera un errore — WHERE non può fare riferimento a un risultato di funzione aggregata, perché viene eseguito PRIMA che l'aggregazione esista.
🔗 Combinare WHERE e HAVING nella stessa query
SELECT corso, AVG(voto) AS media FROM iscrizioni WHERE anno = 2026 -- filtra le RIGHE prima del raggruppamento GROUP BY corso HAVING AVG(voto) >= 25; -- filtra i GRUPPI dopo l'aggregazione
✅ Puoi (e spesso devi) usare entrambe nella stessa query: WHERE per escludere righe irrilevanti in anticipo (più efficiente), HAVING per filtrare in base al risultato aggregato che solo dopo il raggruppamento esiste davvero.
🧩 Query completa — tutti i concetti insieme
SELECT c.titolo AS corso, COUNT(*) AS iscritti, AVG(v.voto) AS media FROM corsi c INNER JOIN iscrizioni i ON c.id = i.corso_id INNER JOIN voti v ON i.id = v.iscrizione_id WHERE c.attivo = 1 GROUP BY c.titolo HAVING COUNT(*) >= 3 ORDER BY media DESC LIMIT 10;
💡 Questa query combina TUTTI i concetti visti nelle guide MySQL: JOIN (collegare tabelle), WHERE (filtrare righe), GROUP BY (raggruppare), funzioni aggregate (COUNT/AVG), HAVING (filtrare gruppi), ORDER BY e LIMIT (ordinare e limitare) — la struttura tipica di una query di reportistica reale, come quelle che costruirai nei progetti CMS/CRM.