L'agrégation conditionnelle est une tâche classique pour les rapports. Au départ, différents indicateurs étaient calculés avec des requêtes distinctes avec des filtres. Très vite, une solution plus compacte est apparue : l'agrégation conditionnelle utilisant CASE à l'intérieur des fonctions d'agrégation (par exemple, SUM(CASE WHEN ...)). Le problème se manifeste lors de la combinaison de filtres, de regroupements et de titres de résumés : il est facile d'obtenir des sommes incorrectes ou d'interpréter le résultat de manière erronée.
Solution : utiliser l'agrégation conditionnelle à l'intérieur des fonctions d'agrégation. Par exemple, pour afficher le nombre de commandes "en traitement" et "terminées" pour tous les employés :
SELECT employee_id, SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END) as processing_count, SUM(CASE WHEN status = 'done' THEN 1 ELSE 0 END) as done_count FROM Orders GROUP BY employee_id;
Caractéristiques clés :
Que se passe-t-il si la condition CASE renvoie NULL au lieu de 0 ?
La fonction d'agrégation SUM ignore NULL. Par conséquent, si l'on écrit CASE WHEN ... THEN 1 END, les lignes omises ne seront pas prises en compte. Il est préférable de définir explicitement ELSE 0.
SUM(CASE WHEN status = 'processing' THEN 1 ELSE 0 END)
Le filtre WHERE peut-il modifier la somme totale des statuts lors de l'agrégation conditionnelle ?
Oui : si le WHERE principal limite l'échantillonnage (par exemple, WHERE region = 'west'), alors les calculs se feront uniquement sur les données filtrées. Pour les totaux globaux, utilisez une sous-requête ou retirez le filtre.
Peut-on utiliser HAVING pour filtrer les lignes avant le regroupement ?
Non. HAVING filtre les données déjà regroupées par agrégats. Le filtrage des lignes d'origine se fait par WHERE.
Dans un rapport analytique, on utilisait :
SUM(CASE WHEN status = 'approved' THEN 1 END)
Il y avait beaucoup de NULL, les sommes finales étaient sous-estimées. À cause du filtre WHERE, certaines lignes nécessaires étaient perdues.
Avantages :
Inconvénients :
On utilisait :
SUM(CASE WHEN status = 'approved' THEN 1 ELSE 0 END)
Le code était maintenu dans une seule requête, les filtres sur le total étaient effectués via HAVING.
Avantages :
Inconvénients :