Dans le langage SQL, la commande “CASE … WHEN …” permet d’utiliser des conditions de type “si / sinon” (cf. if / else) similaire à un langage de programmation pour retourner un résultat disponible entre plusieurs possibilités. Le CASE peut être utilisé dans n’importe quelle instruction ou clause, telle que SELECT, UPDATE, DELETE, WHERE, ORDER BY ou HAVING.
Syntaxe
L’utilisation du CASE est possible de 2 manières différentes :
- Comparer une colonne à un set de résultat possible
- Élaborer une série de conditions booléennes pour déterminer un résultat
Comparer une colonne à un set de résultat
Voici la syntaxe nécessaire pour comparer une colonne à un set d’enregistrement :
CASE a WHEN 1 THEN 'un' WHEN 2 THEN 'deux' WHEN 3 THEN 'trois' ELSE 'autre' END
Dans cet exemple les valeurs contenus dans la colonne “a” sont comparé à 1, 2 ou 3. Si la condition est vrai, alors la valeur située après le THEN sera retournée.
A noter : la condition ELSE est facultative et sert de ramasse-miette. Si les conditions précédentes ne sont pas respectées alors ce sera la valeur du ELSE qui sera retournée par défaut.
Élaborer une série de conditions booléennes pour déterminer un résultat
Il est possible d’établir des conditions plus complexes pour récupérer un résultat ou un autre. Cela s’effectue en utilisant la syntaxe suivante:
CASE WHEN a=b THEN 'A égal à B' WHEN a>b THEN 'A supérieur à B' ELSE 'A inférieur à B' END
Dans cet exemple les colonnes “a”, “b” et “c” peuvent contenir des valeurs numériques. Lorsqu’elles sont respectées, les conditions booléennes permettent de rentrer dans l’une ou l’autre des conditions.
Il est possible de reproduire le premier exemple présenté sur cette page en utilisant la syntaxe suivante:
CASE WHEN a=1 THEN 'un' WHEN a=2 THEN 'deux' WHEN a=3 THEN 'trois' ELSE 'autre' END
Exemple
Pour présenter le CASE dans le langage SQL il est possible d’imaginer une base de données utilisées par un site de vente en ligne. Dans cette base il y a une table contenant les achats, cette table contient le nom des produits, le prix unitaire, la quantité achetée et une colonne consacrée à une marge fictive sur certains produits.
Table “achat” :
id | nom | surcharge | prix_unitaire | quantite |
---|---|---|---|---|
1 | Produit A | 1.3 | 6 | 3 |
2 | Produit B | 1.5 | 8 | 2 |
3 | Produit C | 0.75 | 7 | 4 |
4 | Produit D | 1 | 15 | 2 |
Afficher un message selon une condition
Il est possible d’effectuer une requête qui va afficher un message personnalisé en fonction de la valeur de la marge. Le message sera différent selon que la marge soit égale à 1, supérieur à 1 ou inférieure à 1. La requête peut se présenter de la façon suivante:
SELECT id, nom, marge_pourcentage, prix_unitaire, quantite, CASE WHEN marge_pourcentage=1 THEN 'Prix ordinaire' WHEN marge_pourcentage>1 THEN 'Prix supérieur à la normale' ELSE 'Prix inférieur à la normale' END FROM `achat`
Résultat :
id | nom | surcharge | prix_unitaire | quantite | CASE |
---|---|---|---|---|---|
1 | Produit A | 1.3 | 6 | 3 | Prix supérieur à la normale |
2 | Produit B | 1.5 | 8 | 2 | Prix supérieur à la normale |
3 | Produit C | 0.75 | 7 | 4 | Prix inférieur à la normale |
4 | Produit D | 1 | 15 | 2 | Prix ordinaire |
Ce résultat montre qu’il est possible d’afficher facilement des messages personnalisés selon des conditions simples.
Afficher un prix unitaire différent selon une condition
Avec un CASE il est aussi possible d’utiliser des requêtes plus élaborées. Imaginons maintenant que nous souhaitions multiplier le prix unitaire par 2 si la marge est supérieur à 1, la diviser par 2 si la marge est inférieure à 1 et laisser le prix unitaire tel quel si la marge est égale à 1. C’est possible grâce à la requête SQL:
SELECT id, nom, marge_pourcentage, prix_unitaire, quantite, CASE WHEN marge_pourcentage=1 THEN prix_unitaire WHEN marge_pourcentage>1 THEN prix_unitaire*2 ELSE prix_unitaire/2 END FROM `achat`
Résultat :
id | nom | surcharge | prix_unitaire | quantite | CASE |
---|---|---|---|---|---|
1 | Produit A | 1.3 | 6 | 3 | 12 |
2 | Produit B | 1.5 | 8 | 2 | 16 |
3 | Produit C | 0.75 | 7 | 4 | 3.5 |
4 | Produit D | 1 | 15 | 2 | 15 |
Comparer un champ à une valeur donnée
Imaginons maintenant que l’application propose des réductions selon le nombre de produits achetés:
- 1 produit acheté permet d’obtenir une réduction de -5% pour le prochain achat
- 2 produit acheté permet d’obtenir une réduction de -6% pour le prochain achat
- 3 produit acheté permet d’obtenir une réduction de -8% pour le prochain achat
- Pour plus de produits achetés il y a un réduction de -10% pour le prochain achat
Pour effectuer une telle procédure, il est possible de comparer la colonne “quantite” aux différentes valeurs spécifiée et d’afficher un message personnalisé en fonction du résultat. Cela peut être réalisé avec cette requête SQL:
SELECT id, nom, marge_pourcentage, prix_unitaire, quantite, CASE quantite WHEN 0 THEN 'Erreur' WHEN 1 THEN 'Offre de -5% pour le prochain achat' WHEN 2 THEN 'Offre de -6% pour le prochain achat' WHEN 3 THEN 'Offre de -8% pour le prochain achat' ELSE 'Offre de -10% pour le prochain achat' END FROM `achat`
Résultat :
id | nom | surcharge | prix_unitaire | quantite | CASE |
---|---|---|---|---|---|
1 | Produit A | 1.3 | 6 | 3 | Offre de -8% pour le prochain achat |
2 | Produit B | 1.5 | 8 | 2 | Offre de -6% pour le prochain achat |
3 | Produit C | 0.75 | 7 | 4 | Offre de -10% pour le prochain achat |
4 | Produit D | 1 | 15 | 2 | Offre de -6% pour le prochain achat |
Astuce : la condition ELSE peut parfois être utilisée pour gérer les erreurs.
UPDATE avec CASE
Comme cela a été expliqué au début, il est aussi possible d’utiliser le CASE à la suite de la commande SET d’un UPDATE pour mettre à jour une colonne avec une données spécifique selon une règle. Imaginons par exemple que l’ont souhaite offrir un produit pour tous les achats qui ont une surcharge inférieur à 1 et que l’ont souhaite retirer un produit pour tous les achats avec une surcharge supérieur à 1. Il est possible d’utiliser la requête SQL suivante:
UPDATE `achat` SET `quantite` = ( CASE WHEN `surcharge` < 1 THEN `quantite` + 1 WHEN `surcharge` > 1 THEN `quantite` - 1 ELSE quantite END )