Les fonctions d'agrégation permettent de résumer plusieurs lignes en une seule valeur : total, moyenne, nombre d'éléments, etc. Combinées à GROUP BY, elles deviennent l'un des outils les plus puissants du SQL.
Aggregate functions let you summarize multiple rows into a single value: total, average, count, and so on. Combined with GROUP BY, they become one of SQL's most powerful tools.
Les fonctions d'agrégation de base
The Basic Aggregate Functions
| Fonction | Rôle |
|---|---|
| COUNT(*) | Compte le nombre de lignes |
| SUM(colonne) | Additionne les valeurs |
| AVG(colonne) | Calcule la moyenne |
| MIN(colonne) / MAX(colonne) | Trouve la valeur minimale / maximale |
| Function | Role |
|---|---|
| COUNT(*) | Counts the number of rows |
| SUM(column) | Adds up the values |
| AVG(column) | Calculates the average |
| MIN(column) / MAX(column) | Finds the minimum / maximum value |
SELECT COUNT(*) AS nb_commandes, SUM(montant) AS total
FROM commandes;
SELECT COUNT(*) AS order_count, SUM(amount) AS total
FROM orders;
GROUP BY : regrouper avant d'agréger
GROUP BY: Grouping Before Aggregating
GROUP BY regroupe les lignes ayant la même valeur dans une ou plusieurs colonnes, puis applique la fonction d'agrégation à chaque groupe séparément.
GROUP BY groups rows that share the same value in one or more columns, then applies the aggregate function to each group separately.
SELECT client_id, COUNT(*) AS nb_commandes, SUM(montant) AS total
FROM commandes
GROUP BY client_id;
SELECT customer_id, COUNT(*) AS order_count, SUM(amount) AS total
FROM orders
GROUP BY customer_id;
Règle importante : toute colonne présente dans le SELECT qui n'est pas dans une fonction d'agrégation doit apparaître dans le GROUP BY.
Important rule: any column in the SELECT that isn't inside an aggregate function must appear in the GROUP BY.
HAVING : filtrer après l'agrégation
HAVING: Filtering After Aggregation
WHERE filtre les lignes avant le regroupement ; HAVING filtre les groupes après le calcul de l'agrégation. C'est la confusion la plus fréquente chez les débutants.
WHERE filters rows before grouping; HAVING filters groups after the aggregation is computed. This is the most common point of confusion for beginners.
SELECT client_id, SUM(montant) AS total
FROM commandes
WHERE montant > 0
GROUP BY client_id
HAVING SUM(montant) > 200;
SELECT customer_id, SUM(amount) AS total
FROM orders
WHERE amount > 0
GROUP BY customer_id
HAVING SUM(amount) > 200;
WHERE SUM(montant) > 200 — au moment où WHERE s'exécute, l'agrégation n'a pas encore eu lieu. Utilisez toujours HAVING pour filtrer sur un résultat agrégé.
Tip: you can't write WHERE SUM(amount) > 200 — at the point WHERE runs, aggregation hasn't happened yet. Always use HAVING to filter on an aggregated result.
L'ordre réel d'exécution d'une requête SQL
The Actual Execution Order of a SQL Query
Contrairement à l'ordre dans lequel on écrit une requête, le moteur SQL l'exécute dans cet ordre logique :
Unlike the order in which you write a query, the SQL engine executes it in this logical order:
FROM— identifier les tablesWHERE— filtrer les lignes individuellesGROUP BY— regrouper les lignes restantesHAVING— filtrer les groupesSELECT— choisir les colonnes et calculer les agrégationsORDER BY— trier le résultat finalLIMIT— limiter le nombre de lignes renvoyées
FROM— identify the tablesWHERE— filter individual rowsGROUP BY— group the remaining rowsHAVING— filter the groupsSELECT— choose columns and compute aggregationsORDER BY— sort the final resultLIMIT— limit the number of rows returned
Comprendre cet ordre explique pourquoi on ne peut pas utiliser un alias du SELECT dans le WHERE, mais qu'on peut souvent l'utiliser dans ORDER BY.
Understanding this order explains why you can't use a SELECT alias in WHERE, but can often use it in ORDER BY.
Exemple complet
Full Example
SELECT
c.nom,
COUNT(co.id) AS nb_commandes,
SUM(co.montant) AS total_depense
FROM clients c
LEFT JOIN commandes co ON co.client_id = c.id
GROUP BY c.nom
HAVING COUNT(co.id) >= 1
ORDER BY total_depense DESC
LIMIT 10;
SELECT
c.name,
COUNT(o.id) AS order_count,
SUM(o.amount) AS total_spent
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
GROUP BY c.name
HAVING COUNT(o.id) >= 1
ORDER BY total_spent DESC
LIMIT 10;
Cette requête retourne les 10 clients ayant dépensé le plus, classés par montant décroissant, en excluant ceux sans aucune commande.
This query returns the top 10 highest-spending customers, ranked in descending order, excluding those with no orders at all.
