SQL CASE WHEN : écrire des conditions dans une requête
« Si le prix dépasse 100 €, afficher premium, sinon standard ». Pour ce type de logique, SQL propose l'expression CASE WHEN, l'équivalent du « si… alors… sinon » des langages de programmation. On peut l'utiliser partout où une valeur est attendue : dans le SELECT, le ORDER BY, et même à l'intérieur d'un SUM.
Syntaxe
CASE
WHEN condition1 THEN valeur1
WHEN condition2 THEN valeur2
ELSE valeur_par_defaut
ENDComment ça marche
SQL teste les conditions WHEN dans l'ordre et renvoie la valeur de la première condition vraie. Si aucune n'est vraie, il renvoie la valeur du ELSE, ou NULL s'il n'y a pas de ELSE. Le mot END termine l'expression ; on lui donne souvent un alias avec AS.
Une forme raccourcie
Pour comparer une seule colonne à plusieurs valeurs : CASE statut WHEN 'livrée' THEN 'OK' WHEN 'annulée' THEN 'KO' ELSE '…' END.
Compter selon une condition
SUM(CASE WHEN condition THEN 1 ELSE 0 END) compte les lignes qui respectent une condition. Avec plusieurs expressions de ce type, on obtient un tableau croisé en une seule requête.
Schéma
| nom | prix |
|---|---|
| Écran | 289 |
| Plaid | 25 |
| SSD | 149 |
| nom | gamme |
|---|---|
| Écran | premium |
| Plaid | standard |
| SSD | premium |
Schéma simplifié pour illustrer le principe. Les exemples ci-dessous utilisent la vraie base d'exercices de SQL Quest (une boutique en ligne fictive : voir le schéma complet).
Exemples avec leurs résultats
1. Créer des catégories
Une gamme de prix calculée pour chaque produit.
SELECT nom, prix,
CASE
WHEN prix >= 100 THEN 'premium'
WHEN prix >= 30 THEN 'intermédiaire'
ELSE 'petit prix'
END AS gamme
FROM produits
ORDER BY prix DESC
LIMIT 8; Essayer dans le bac à sable| nom | prix | gamme |
|---|---|---|
| Écran 27" | 342 | premium |
| SSD 1To | 317 | premium |
| Souris sans fil | 103 | premium |
| Webcam HD | 101 | premium |
| Casque gaming | 98 | intermédiaire |
| Bougie parfumée | 60,92 | intermédiaire |
| Lampe LED | 51,74 | intermédiaire |
| Hub USB-C | 49 | intermédiaire |
8 lignes au total
2. Regrouper sur une catégorie calculée
Le nombre de clients par tranche d'âge.
SELECT
CASE
WHEN age IS NULL THEN 'inconnu'
WHEN age < 30 THEN 'moins de 30 ans'
WHEN age < 50 THEN '30 à 49 ans'
ELSE '50 ans et plus'
END AS tranche,
COUNT(*) AS nb
FROM clients
GROUP BY tranche
ORDER BY nb DESC; Essayer dans le bac à sable| tranche | nb |
|---|---|
| 50 ans et plus | 50 |
| 30 à 49 ans | 47 |
| moins de 30 ans | 19 |
| inconnu | 4 |
4 lignes au total
3. Compter selon une condition
Pour chaque année, le nombre total de commandes et le nombre de commandes annulées.
SELECT strftime('%Y', date_commande) AS annee,
COUNT(*) AS total,
SUM(CASE WHEN statut = 'annulée' THEN 1 ELSE 0 END) AS annulees
FROM commandes
GROUP BY annee; Essayer dans le bac à sable| annee | total | annulees |
|---|---|---|
| 2023 | 190 | 39 |
| 2024 | 214 | 28 |
| 2025 | 196 | 25 |
3 lignes au total
Les erreurs fréquentes
Oublier END
Chaque CASE doit se terminer par END, sinon la requête provoque une erreur de syntaxe.
SELECT nom, CASE WHEN prix > 100 THEN 'cher' ELSE 'abordable' AS gamme FROM produits;SELECT nom, CASE WHEN prix > 100 THEN 'cher' ELSE 'abordable' END AS gamme FROM produits;Mettre les conditions dans le mauvais ordre
La première condition vraie gagne : ici, un prix de 300 € est classé « intermédiaire » car prix >= 30 est testé en premier.
SELECT nom, CASE WHEN prix >= 30 THEN 'intermédiaire' WHEN prix >= 100 THEN 'premium' END FROM produits;SELECT nom, CASE WHEN prix >= 100 THEN 'premium' WHEN prix >= 30 THEN 'intermédiaire' END FROM produits;Oublier le ELSE
Sans ELSE, les lignes qui ne respectent aucune condition reçoivent NULL, ce qui fausse souvent les calculs.
SELECT SUM(CASE WHEN statut = 'livrée' THEN 1 END) FROM commandes;SELECT SUM(CASE WHEN statut = 'livrée' THEN 1 ELSE 0 END) FROM commandes;Exercices
Essayez d'écrire la requête vous-même avant d'ouvrir la solution.
Défi 1. Affichez chaque produit avec une colonne « disponibilite » : « rupture » si le stock vaut 0, « faible » en dessous de 20, sinon « ok ».
Voir une solution
SELECT nom, stock, CASE WHEN stock = 0 THEN 'rupture' WHEN stock < 20 THEN 'faible' ELSE 'ok' END AS disponibilite FROM produits;| nom | stock | disponibilite |
|---|---|---|
| Clavier mécanique | 105 | ok |
| Souris sans fil | 75 | ok |
| Écran 27" | 102 | ok |
| Webcam HD | 21 | ok |
| SSD 1To | 90 | ok |
| Casque gaming | 37 | ok |
| Hub USB-C | 162 | ok |
| Lampe LED | 15 | faible |
29 lignes au total · 8 affichées
Essayer dans le bac à sableDéfi 2. Pour chaque ville, comptez les clients de moins de 30 ans et ceux de 30 ans et plus.
Voir une solution
SELECT ville, SUM(CASE WHEN age < 30 THEN 1 ELSE 0 END) AS jeunes, SUM(CASE WHEN age >= 30 THEN 1 ELSE 0 END) AS autres FROM clients GROUP BY ville;| ville | jeunes | autres |
|---|---|---|
| Bordeaux | 4 | 9 |
| Bruxelles | 0 | 8 |
| Casablanca | 2 | 8 |
| Genève | 0 | 5 |
| Lille | 3 | 6 |
| Lyon | 1 | 11 |
| Marseille | 1 | 9 |
| Montréal | 3 | 7 |
12 lignes au total · 8 affichées
Essayer dans le bac à sableLes exercices interactifs sont corrigés automatiquement, avec un prof qui explique vos erreurs. Une leçon résumée reste affichée à côté de l'éditeur.
Questions fréquentes
Peut-on utiliser CASE dans un WHERE ?
Oui, mais c'est rarement nécessaire : une combinaison de AND et OR est en général plus simple à lire.
Existe-t-il une fonction IF en SQL ?
MySQL a IF(condition, a, b) et SQLite a IIF(condition, a, b) depuis la version 3.32. CASE WHEN est la version standard, valable partout.
Les valeurs de THEN doivent-elles être du même type ?
C'est fortement recommandé. Mélanger du texte et des nombres fonctionne en SQLite, mais provoque des erreurs ou des conversions dans d'autres bases.