Tu as sûrement déjà croisé des expressions conditionnelles dans des langages de programmation : if-else, switch-case et ce genre de trucs. En SQL, il y a son propre outil pour bosser avec les conditions : c'est l'expression CASE. Elle te permet de prendre des décisions direct dans les requêtes : si la condition est vraie, tu fais un truc, sinon tu fais autre chose.
La construction CASE est super utile quand tu bosses avec des données qui peuvent contenir des valeurs NULL. Le syntaxe est simple, genre anti-sèche, regarde :
CASE
WHEN condition1 THEN résultat1
WHEN condition2 THEN résultat2
...
ELSE résultat_par_défaut
END
Logique, non ? "Si c'est comme ça, fais ça, sinon fais autre chose". Facile à retenir : "WHEN — c'est si, THEN — c'est quoi faire, ELSE — c'est quoi faire si rien ne correspond".
Exemple : classification des produits
Imagine qu'on a une table products avec une colonne price, et on veut répartir les produits en groupes selon leur prix.
| id | name | price |
|---|---|---|
| 1 | Magic Wand | 120 |
| 2 | Potion Set | 45 |
| 3 | Crystal Ball | 75 |
| 4 | Enchanted Map | NULL |
| 5 | Broomstick | 99 |
| 6 | Spell Book | 180 |
SELECT
name AS product_name,
price,
CASE
WHEN price IS NULL THEN 'Inconnu'
WHEN price < 50 THEN 'Économique'
WHEN price BETWEEN 50 AND 100 THEN 'Standard'
ELSE 'Premium'
END AS price_category
FROM products;
Qu'est-ce qui se passe ici ?
- Si le prix
pricedu produit n'est pas renseignéNULL, on affiche la catégorie comme'Inconnu'. - Si le prix est inférieur à 50, le produit est considéré comme économique
'Économique'. - Si le prix est entre 50 et 100, il tombe dans la catégorie
'Standard'. - Tout le reste — c'est des produits premium
'Premium'.
Voilà le résultat :
| product_name | price | price_category |
|---|---|---|
| Magic Wand | 120 | Premium |
| Potion Set | 45 | Économique |
| Crystal Ball | 75 | Standard |
| Enchanted Map | NULL | Inconnu |
| Broomstick | 99 | Standard |
| Spell Book | 180 | Premium |
SQL, comme un magicien, lit les lignes de la table products, applique la logique à chaque ligne et classe tout ça malin.
Travailler avec NULL dans CASE WHEN
Souvent, il y a des valeurs manquantes dans les données (coucou NULL), et il faut les remplacer par autre chose. Par exemple, on a une table users avec une colonne email, et pour les utilisateurs sans email, on veut afficher 'Non renseigné'.
| user_id | name | |
|---|---|---|
| 1 | Alex Lin | alex@example.com |
| 2 | Maria Chi | NULL |
| 3 | Anna Song | anna@magic.com |
| 4 | Otto Art | NULL |
| 5 | John Smith | john@wizard.org |
SELECT
user_id,
name,
CASE
WHEN email IS NULL THEN 'Non renseigné'
ELSE email
END AS email_address
FROM users;
| user_id | name | email_address |
|---|---|---|
| 1 | Alex Lin | alex@example.com |
| 2 | Maria Chi | Non renseigné |
| 3 | Anna Song | anna@magic.com |
| 4 | Otto Art | Non renseigné |
| 5 | John Smith | john@wizard.org |
SQL ici fait le chaman : il redonne vie aux lignes à moitié vides. Si l'email manque, il le remplace par 'Non renseigné'. Si l'email existe — il le garde tel quel.
Expressions conditionnelles avec des nombres
Parfois, il ne s'agit pas juste de remplacer des valeurs, mais de construire une nouvelle logique. Par exemple, imaginons qu'on a une table students avec les colonnes score (note) et name.
| name | score |
|---|---|
| Alex Lin | 95 |
| Maria Chi | 82 |
| Anna Song | 48 |
| Otto Art | NULL |
| John Smith | 67 |
| Zoe Black | 30 |
On veut évaluer les étudiants comme "Excellent", "Passable" et "Échec", selon leurs notes.
SELECT
name AS student_name,
score,
CASE
WHEN score IS NULL THEN 'Pas de note'
WHEN score >= 90 THEN 'Excellent'
WHEN score >= 50 THEN 'Passable'
ELSE 'Échec'
END AS performance_category
FROM students;
| student_name | score | performance_category |
|---|---|---|
| Alex Lin | 95 | Excellent |
| Maria Chi | 82 | Passable |
| Anna Song | 48 | Échec |
| Otto Art | NULL | Pas de note |
| John Smith | 67 | Passable |
| Zoe Black | 30 | Échec |
SQL distribue gentiment les étudiants, comme un examinateur sévère : 90 points et plus — c'est "Excellent", à partir de 50 — "Passable". Et si ça ne suffit pas... tu vois le délire.
Groupement et gestion des NULL
Travailler avec des groupes de données — c'est encore un domaine où CASE WHEN brille. Imagine qu'on a une table orders, et on veut compter le nombre total de commandes par statut, y compris celles avec un statut NULL.
| order_id | status |
|---|---|
| 1 | Completed |
| 2 | Pending |
| 3 | NULL |
| 4 | Shipped |
| 5 | Completed |
| 6 | NULL |
| 7 | Pending |
| 8 | Completed |
| 9 | Shipped |
| 10 | NULL |
SELECT
CASE
WHEN status IS NULL THEN 'Aucun statut'
ELSE status
END AS order_status,
COUNT(*)
FROM orders
GROUP BY
CASE
WHEN status IS NULL THEN 'Aucun statut'
ELSE status
END;
Cette requête gère proprement les statuts NULL et met 'Aucun statut' à la place, puis compte le nombre total de commandes dans chaque groupe. Voilà le résultat :
| order_status | count |
|---|---|
| Completed | 3 |
| Pending | 2 |
| Shipped | 2 |
| Aucun statut | 3 |
Cas pratiques : "Tours de magie" avec CASE WHEN
Exemple 1 : Tri en tenant compte des NULL
Parfois, il faut afficher les valeurs NULL soit en premier, soit en dernier dans une liste triée. C'est souvent utilisé, par exemple, dans les listes de tâches où les tâches prioritaires doivent être en haut, et celles sans priorité (NULL) à la fin.
| task_id | task_name | priority |
|---|---|---|
| 1 | Fix bugs | 1 |
| 2 | Update documentation | 3 |
| 3 | Plan sprint | NULL |
| 4 | Code review | 2 |
| 5 | Organize meeting | NULL |
| 6 | Deploy release | 1 |
SELECT
task_name,
priority,
CASE
WHEN priority IS NULL THEN 1
ELSE 0
END AS priority_sort
FROM tasks
ORDER BY priority_sort ASC, priority ASC;
Ici, on a ajouté une colonne "virtuelle" priority_sort qui met les NULL tout en bas, et le reste est trié par ordre croissant.
| task_name | priority | priority_sort |
|---|---|---|
| Deploy release | 1 | 0 |
| Fix bugs | 1 | 0 |
| Code review | 2 | 0 |
| Update documentation | 3 | 0 |
| Plan sprint | NULL | 1 |
| Organize meeting | NULL | 1 |
Exemple 2 : Calculs avec NULL
Maintenant, imagine qu'on calcule le montant final d'une commande dans la table orders, où la colonne discount peut être NULL si y'a pas de remise.
| order_id | total_price | discount |
|---|---|---|
| 101 | 100 | 10 |
| 102 | 200 | NULL |
| 103 | 150 | 15 |
| 104 | 120 | NULL |
| 105 | 80 | 5 |
On doit remplacer NULL par 0 pour que le calcul ne parte pas en vrille.
SELECT
order_id,
total_price,
discount,
total_price -
CASE
WHEN discount IS NULL THEN 0
ELSE discount
END AS final_price
FROM orders;
| order_id | total_price | discount | final_price |
|---|---|---|---|
| 101 | 100 | 10 | 90 |
| 102 | 200 | NULL | 200 |
| 103 | 150 | 15 | 135 |
| 104 | 120 | NULL | 120 |
| 105 | 80 | 5 | 75 |
Ce petit tour de magie avec CASE nous garantit que NULL ne va pas casser les calculs.
Pour orderid = 101 : discount = 10. finalprice = 100 - 10 = 90. Pour orderid = 102 : discount = NULL. CASE renvoie 0. finalprice = 200 - 0 = 200. Pour orderid = 103 : discount = 15. finalprice = 150 - 15 = 135. Pour orderid = 104 : discount = NULL. CASE renvoie 0. finalprice = 120 - 0 = 120. Pour orderid = 105 : discount = 5. finalprice = 80 - 5 = 75.
Exemple 3 : Affichage des statuts utilisateurs
Dans la vie de tous les jours, on doit souvent afficher le statut d'un utilisateur (genre "Actif" ou "En attente") ou signaler l'absence de données. Par exemple, dans la table users il y a une colonne last_login qui stocke la date de dernière connexion.
| user_id | name | last_login |
|---|---|---|
| 1 | Alex Lin | 2024-12-10 |
| 2 | Maria Chi | 2025-04-20 |
| 3 | Anna Song | NULL |
| 4 | Otto Art | 2025-05-01 |
| 5 | Liam Park | 2025-05-25 |
SELECT
user_id,
name,
CASE
WHEN last_login IS NULL THEN 'Jamais connecté'
WHEN last_login < CURRENT_DATE - INTERVAL '30 days' THEN 'Inactif'
ELSE 'Actif'
END AS user_status
FROM users;
Avec cette requête, le système d'admin prend vie : les utilisateurs jamais connectés sont "Jamais connecté", ceux qui ne sont pas venus depuis longtemps sont "Inactif". Les autres sont actifs !
| user_id | name | user_status |
|---|---|---|
| 1 | Alex Lin | Inactif |
| 2 | Maria Chi | Inactif |
| 3 | Anna Song | Jamais connecté |
| 4 | Otto Art | Inactif |
| 5 | Liam Park | Actif |
Erreurs fréquentes et comment les éviter
Oublier ELSE : Si tu n'ajoutes pas ELSE, SQL va juste renvoyer NULL si aucune condition n'est remplie. C'est pas toujours ce que tu veux. Donc, mieux vaut toujours mettre ELSE, même si t'es sûr d'avoir tout couvert.
CASE
WHEN condition THEN résultat
-- ELSE 'Valeur par défaut' -- n'oublie pas !
END
Conditions complexes sans parenthèses : Si t'as plusieurs conditions avec AND, OR ou NOT, mets toujours des parenthèses. Sinon ta requête peut "penser" de travers.
CASE
WHEN (column1 IS NOT NULL AND column2 > 5) THEN 'Valide'
ELSE 'Invalide'
END
Travailler avec NULL : Rappelle-toi que NULL n'est jamais égal (=) à quoi que ce soit. Par exemple :
CASE
WHEN column = NULL THEN 'Nope!' -- Erreur !
WHEN column IS NULL THEN 'Correct !' -- Ça c'est bon.
END
GO TO FULL VERSION