ProgrammationDéveloppeur Backend, Analyste BI

Comment mettre en œuvre une agrégation fiable avec des conditions uniques (agrégation conditionnelle) en SQL lors de l'élaboration de rapports avec plusieurs filtres ? Quelles subtilités existent lors de la combinaison de HAVING, CASE et des fonctions d'agrégation ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

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 :

  • Indépendamment du filtre WHERE, toutes les sommes nécessaires sont calculées dans une seule requête.
  • CASE à l'intérieur de SUM permet de construire des rapports complexes avec plusieurs indicateurs.
  • HAVING s'applique aux données déjà agrégées, pour le post-filtrage du résultat de regroupement.

Questions pièges.

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.

Erreurs typiques et anti-modèles

  • Pas de ELSE, CASE renvoie NULL, résultats incorrects.
  • Mélangent WHERE et HAVING, obtenant les mauvaises lignes.
  • Utilisent plusieurs requêtes au lieu d'une seule avec CASE.

Exemple de la vie réelle

Cas négatif

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 :

  • Code court.

Inconvénients :

  • Résultats incorrects, rapport mal expliqué aux affaires.

Cas positif

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 :

  • Indicateurs corrects et transparents.
  • Facile d'ajouter un nouveau statut.

Inconvénients :

  • Les requêtes deviennent plus longues, un soin est nécessaire avec les filtres.