L'agrégation conditionnelle est utilisée lorsqu'il est nécessaire d'agréger des valeurs (par exemple, la somme ou le nombre) selon différentes conditions dans le cadre d'une seule requête. Historiquement, pour atteindre de tels objectifs, les développeurs SQL devaient écrire de multiples sous-requêtes ou effectuer des jointures et des regroupements séparément pour chaque catégorie, ce qui conduisait à un code moins lisible et moins performant.
Le problème résidait dans la difficulté de calculer simultanément plusieurs agrégats avec différentes conditions — chaque agrégat nécessite généralement un filtrage, et l'application simple de SUM() ou COUNT() ne prend pas en compte la condition requise à l'intérieur de la fonction d'agrégation.
Solution — utiliser la construction CASE à l'intérieur de la fonction d'agrégation, ce qui permet de "séparer" les agrégats selon différentes conditions à la volée, sans avoir recours à plusieurs jointures :
Exemple de code :
SELECT department, SUM(CASE WHEN status = 'approved' THEN amount ELSE 0 END) AS approved_sum, SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) AS pending_sum, COUNT(CASE WHEN status = 'rejected' THEN 1 END) AS rejected_count FROM payments GROUP BY department;
Caractéristiques clés :
Peut-on se passer de la construction CASE pour l'agrégation conditionnelle ?
Une réponse incorrecte serait d'utiliser WHERE directement dans la requête avec la fonction d'agrégation. En réalité, WHERE filtre les lignes avant l'agrégation, et non à l'intérieur de chaque colonne agrégée.
Exemple de code (méthode incorrecte) :
SELECT COUNT(*) FROM payments WHERE status = 'approved'; SELECT COUNT(*) FROM payments WHERE status = 'pending';
Ces requêtes ne peuvent pas être combinées en une seule ligne de résultat selon différentes conditions sans CASE.
Que se passe-t-il si l'on utilise NULL dans l'expression conditionnelle ?
Si CASE ne renvoie pas de valeur alternative, elle sera par défaut NULL, et la fonction d'agrégation ignorera NULL.
Exemple de code :
SUM(CASE WHEN status = 'approved' THEN amount END) -- Si le statut n'est pas 'approved', alors NULL, et la ligne est ignorée dans SUM
Peut-on utiliser IF à la place de CASE ?
Dans certains dialectes SQL (par exemple, MySQL), c'est possible, mais ce code devient non portable entre différentes bases de données. Dans les requêtes universelles, utilisez toujours CASE.
Un analyste a tenté de calculer des sommes par statut en écrivant plusieurs sous-requêtes séparées. Le rapport externe est devenu complexe, et l'ajout de nouveaux statuts a nécessité de réécrire le code à chaque fois.
Avantages :
Un développeur a utilisé CASE dans une seule requête générale, créant un rapport universel avec la possibilité d'élargir pour de nouveaux statuts par une simple modification d'une requête.
Avantages :