📊 Fonctions d'agrégation
Les fonctions d'agrégation calculent une valeur à partir d'un ensemble de lignes. Elles s'utilisent dans le SELECT ou le HAVING.
| Fonction | Description | Exemple |
|---|---|---|
COUNT(*) | Nombre de lignes (inclut NULL) | COUNT(*) |
COUNT(col) | Lignes non-NULL de la colonne | COUNT(email) |
SUM(col) | Somme | SUM(total) |
AVG(col) | Moyenne (ignore NULL) | AVG(prix) |
MIN(col) | Valeur minimale | MIN(prix) |
MAX(col) | Valeur maximale | MAX(date_commande) |
-- Sans GROUP BY : agrège toute la table
SELECT
COUNT(*) AS nb_produits,
ROUND(AVG(prix), 2) AS prix_moyen,
MIN(prix) AS prix_min,
MAX(prix) AS prix_max,
ROUND(SUM(prix * stock), 2) AS valeur_stock
FROM produits;
📦 GROUP BY
GROUP BY regroupe les lignes ayant la même valeur dans une ou plusieurs colonnes. Les fonctions d'agrégation s'appliquent ensuite à chaque groupe.
-- Nombre de produits par catégorie
SELECT categorie_id, COUNT(*) AS nb_produits
FROM produits
GROUP BY categorie_id;
-- Avec JOIN pour afficher le nom de la catégorie
SELECT c.nom AS categorie, COUNT(p.id) AS nb, ROUND(AVG(p.prix), 2) AS prix_moyen
FROM categories c
LEFT JOIN produits p ON c.id = p.categorie_id
GROUP BY c.id, c.nom
ORDER BY nb DESC;
-- Chiffre d'affaires par mois
SELECT
YEAR(date_commande) AS annee,
MONTH(date_commande) AS mois,
COUNT(*) AS nb_commandes,
SUM(total) AS ca
FROM commandes
WHERE statut != 'annulee'
GROUP BY YEAR(date_commande), MONTH(date_commande)
ORDER BY annee, mois;
En mode
ONLY_FULL_GROUP_BY (activé par défaut depuis MySQL 5.7), toutes les colonnes du SELECT doivent soit être dans le GROUP BY, soit être dans une fonction d'agrégation.🔽 HAVING — Filtrer les groupes
HAVING filtre les groupes après l'agrégation, comme WHERE filtre les lignes avant.
-- Catégories avec plus de 2 produits
SELECT categorie_id, COUNT(*) AS nb
FROM produits
GROUP BY categorie_id
HAVING nb > 2;
-- Clients avec un total d'achats > 500€
SELECT cl.nom, SUM(co.total) AS total
FROM clients cl
JOIN commandes co ON cl.id = co.client_id
GROUP BY cl.id, cl.nom
HAVING total > 500
ORDER BY total DESC;
-- WHERE + HAVING combinés
SELECT c.nom, COUNT(p.id) AS nb, AVG(p.prix) AS moy
FROM categories c
JOIN produits p ON c.id = p.categorie_id
WHERE p.stock > 0 -- filtre AVANT le regroupement
GROUP BY c.id, c.nom
HAVING moy > 50 -- filtre APRÈS le regroupement
ORDER BY moy DESC;
📋 Ordre des clauses SQL
L'ordre des clauses est fixe et ne peut pas être changé :
SELECT colonnes, agrégats, alias
FROM table
JOIN autre_table ON condition
WHERE filtre_lignes_individuelles
GROUP BY colonnes_de_regroupement
HAVING filtre_groupes
ORDER BY colonne ASC|DESC
LIMIT n OFFSET m
📅 Fonctions de date
-- Dates actuelles
SELECT NOW(), -- 2024-01-15 10:30:00
CURDATE(), -- 2024-01-15
CURTIME(); -- 10:30:00
-- Extraction
SELECT YEAR(created_at), MONTH(created_at), DAY(created_at);
SELECT DAYNAME(NOW()), -- lundi / Monday selon la locale
MONTHNAME(NOW());
-- Formatage pour l'affichage
SELECT DATE_FORMAT(created_at, '%d/%m/%Y') AS date_fr FROM commandes;
SELECT DATE_FORMAT(created_at, '%d %M %Y') AS date_longue FROM commandes;
-- Calculs
SELECT DATE_ADD(NOW(), INTERVAL 30 DAY); -- dans 30 jours
SELECT DATE_SUB(NOW(), INTERVAL 1 YEAR); -- il y a 1 an
SELECT DATEDIFF('2024-12-31', '2024-01-01'); -- 364 jours
-- Requêtes fréquentes
SELECT * FROM commandes WHERE date_commande >= NOW() - INTERVAL 7 DAY;
SELECT * FROM commandes WHERE MONTH(date_commande) = MONTH(NOW())
AND YEAR(date_commande) = YEAR(NOW());
📝 Fonctions de chaîne utiles
SELECT CONCAT(nom, ' ', prenom) AS nom_complet FROM employes;
SELECT CONCAT_WS(', ', nom, ville) AS adresse FROM clients;
SELECT UPPER(nom), LOWER(email) FROM clients;
SELECT LENGTH('MySQL') -- 5
SELECT CHAR_LENGTH('été') -- 3 (caractères, pas octets)
SELECT LEFT(nom, 3) -- 3 premiers caractères
SELECT RIGHT(email, 10) -- 10 derniers caractères
SELECT TRIM(' espaces ') -- 'espaces'
SELECT REPLACE(nom, 'é', 'e') FROM clients;
SELECT LPAD(id, 6, '0') -- 000042 (padding gauche)
🔗 GROUP_CONCAT
Agrège les valeurs d'un groupe en une seule chaîne.
-- Liste des produits par catégorie
SELECT c.nom AS categorie,
GROUP_CONCAT(p.nom ORDER BY p.nom SEPARATOR ', ') AS produits
FROM categories c
JOIN produits p ON c.id = p.categorie_id
GROUP BY c.id, c.nom;
-- Avec DISTINCT pour éviter les doublons
SELECT client_id,
GROUP_CONCAT(DISTINCT statut ORDER BY statut) AS statuts
FROM commandes
GROUP BY client_id;