CASE ajoute une logique si/alors/sinon à une requête SQL : il vérifie une liste de conditions et renvoie le résultat de la première qui est vraie. Les exemples fonctionnent avec PostgreSQL, MySQL, SQLite et SQL Server.
Comment utiliser CASE
Liste des paires WHEN condition THEN result entre CASE et END. CASE renvoie le résultat de la première condition vraie, ou la valeur de ELSE si aucune ne l’est :
CASE
WHEN condition THEN result
[WHEN condition THEN result ...]
[ELSE result]
END
SELECT
CASE
WHEN 72 >= 90 THEN 'Hot'
WHEN 72 >= 60 THEN 'Mild'
ELSE 'Cold'
END;
-- Output: Mild
Quand chaque condition teste l’égalité d’une même valeur, la forme « simple », plus courte, ne nomme cette valeur qu’une fois :
SELECT
CASE 'amber'
WHEN 'green' THEN 'Go'
WHEN 'amber' THEN 'Slow down'
WHEN 'red' THEN 'Stop'
ELSE 'Unknown'
END;
-- Output: Slow down
Dans une vraie requête, les conditions testent des colonnes, et CASE ajoute une nouvelle colonne au résultat :
-- Input: orders
-- order_id | amount
-- ---------+--------
-- 1001 | 45.00
-- 1002 | 100.00
-- 1003 | 349.99
-- 1004 | 1250.00
SELECT
order_id,
amount,
CASE
WHEN amount < 100 THEN 'Small'
WHEN amount < 500 THEN 'Medium'
ELSE 'Large'
END AS order_size
FROM orders;
-- Output:
-- order_id | amount | order_size
-- ---------+---------+-----------
-- 1001 | 45.00 | Small
-- 1002 | 100.00 | Medium
-- 1003 | 349.99 | Medium
-- 1004 | 1250.00 | Large
Les règles à connaître
-
La première condition vraie l’emporte. Les conditions sont vérifiées de haut en bas, donc mets la plus restrictive en premier. Ci-dessus,
100.00est Medium caramount < 100est faux etamount < 500est vrai. Dans le mauvais ordre, les petits montants n’atteignent jamais leur branche :
SELECT
CASE
WHEN 45 < 500 THEN 'Medium'
WHEN 45 < 100 THEN 'Small' -- can never win
ELSE 'Large'
END;
-- Output: Medium
- Sans ELSE, aucune correspondance donne NULL.
SELECT CASE WHEN 72 >= 90 THEN 'Hot' END;
-- Output: NULL
-
Teste NULL avec IS NULL.
NULL = NULLn’est pas vrai, donc la forme simple ne peut pas détecter un NULL. Utilise la forme avec conditions :
SELECT CASE NULL WHEN NULL THEN 'matched' ELSE 'no match' END;
-- Output: no match
SELECT CASE WHEN NULL IS NULL THEN 'matched' ELSE 'no match' END;
-- Output: matched
- Chaque résultat doit avoir un type compatible. Mélanger un nombre et du texte dans un même CASE échoue dans PostgreSQL et SQL Server, alors convertis le nombre :
-- Input: products
-- name | stock
-- -------------+------
-- Desk Lamp | 12
-- Office Chair | 0
SELECT name, CASE WHEN stock > 0 THEN stock ELSE 'Sold out' END AS stock
FROM products;
-- PostgreSQL: ERROR: invalid input syntax for type integer: "Sold out"
-- SQL Server: Conversion failed when converting the varchar value 'Sold out' to data type int.
-- (in MySQL, cast with CAST(stock AS CHAR))
SELECT
name,
CASE WHEN stock > 0 THEN CAST(stock AS VARCHAR(10)) ELSE 'Sold out' END AS stock
FROM products;
-- Output:
-- name | stock
-- -------------+---------
-- Desk Lamp | 12
-- Office Chair | Sold out
Syntaxe alternative
Pour une seule condition, tu croiseras aussi une fonction plus courte :
-- MySQL
SELECT IF(72 >= 60, 'Mild', 'Cold');
-- Output: Mild
-- SQL Server and SQLite
SELECT IIF(72 >= 60, 'Mild', 'Cold');
-- Output: Mild
Deux autres fonctions sont des raccourcis pour des expressions CASE courantes. COALESCE(nickname, name) équivaut à CASE WHEN nickname IS NOT NULL THEN nickname ELSE name END, et NULLIF(a, b) équivaut à CASE WHEN a = b THEN NULL ELSE a END. Consulte le guide SQL COALESCE pour la première.
MySQL propose aussi une instruction CASE pour les procédures stockées, qui se termine par END CASE. Cet article traite de l’expression CASE que tu utilises dans les requêtes.
Quand utiliser CASE ?
CASE est une expression : elle fonctionne partout où une valeur est acceptée, dans la liste du SELECT, dans ORDER BY et GROUP BY, et dans les fonctions d’agrégation. Elle marche aussi dans WHERE, mais de simples AND et OR y sont généralement plus clairs. La plupart des usages entrent dans l’un de ces cinq cas.
Classer des nombres par tranches
Transforme un nombre en tranche : niveaux de prix, tailles de commande, tranches d’âge, notes. Écris les conditions d’un bout à l’autre de l’échelle, pour que la première correspondance soit la bonne.
Traduire des codes en libellés
Les bases de données stockent des codes courts comme 'A', 'ENG' ou 'gold' ; les humains veulent des mots. Un CASE simple associe chaque code à un libellé, ou à une valeur comme un taux de remise, et ELSE attrape tout code inattendu.
Compter ou totaliser certaines lignes seulement
Place CASE dans COUNT ou SUM pour compter ou additionner uniquement les lignes qui remplissent une condition. COUNT(CASE WHEN ... THEN 1 END) fonctionne car les lignes non concernées donnent NULL, que COUNT ignore. Un agrégat par condition te donne plusieurs totaux côte à côte : c’est ainsi qu’on construit un tableau croisé en SQL.
Gérer les valeurs manquantes
Vérifie les colonnes NULL par ordre de préférence, et renvoie un libellé quand elles sont toutes vides. Pour une simple valeur de repli, COALESCE est plus court. CASE est l’outil idéal quand chaque type de manque exige un résultat différent.
Trier dans un ordre personnalisé
L’ordre alphabétique ou numérique ne convient pas à tout : tailles de vêtements, priorités de tickets, liste avec les produits phares en tête. Un CASE dans ORDER BY donne à chaque valeur la position que tu veux.
Exemples concrets de CASE
Classer les produits par rayon et par prix
Un résultat peut lui-même être un CASE, ce qui donne à chaque rayon ses propres tranches de prix :
-- Input: products
-- product_name | category | price
-- -----------------+-------------+--------
-- Laptop Pro 14 | Electronics | 1499.00
-- Wireless Earbuds | Electronics | 129.00
-- Leather Jacket | Clothing | 349.00
-- Cotton T-Shirt | Clothing | 19.99
-- Coffee Mug | Kitchen | 12.50
SELECT
product_name,
CASE category
WHEN 'Electronics' THEN
CASE
WHEN price > 1000 THEN 'Premium Electronics'
ELSE 'Standard Electronics'
END
WHEN 'Clothing' THEN
CASE
WHEN price > 200 THEN 'Designer Clothing'
ELSE 'Regular Clothing'
END
ELSE 'Other Products'
END AS product_class
FROM products;
-- Output:
-- product_name | product_class
-- -----------------+---------------------
-- Laptop Pro 14 | Premium Electronics
-- Wireless Earbuds | Standard Electronics
-- Leather Jacket | Designer Clothing
-- Cotton T-Shirt | Regular Clothing
-- Coffee Mug | Other Products
Au-delà de deux niveaux, un CASE imbriqué devient difficile à lire. Une table de correspondance avec une jointure est souvent plus claire.
Appliquer une remise selon le niveau du client
Chaque code de niveau correspond à un taux de remise, et les clients sans niveau n’en ont pas :
-- Input: customers
-- id | customer_name | tier
-- ---+---------------+-------
-- 1 | Maya Brooks | gold
-- 2 | Leo Martin | silver
-- 3 | Ava Kim | bronze
-- 4 | Noah Price | NULL
-- Input: orders
-- id | customer_id | order_total
-- ----+-------------+------------
-- 101 | 1 | 200.00
-- 102 | 2 | 150.00
-- 103 | 3 | 80.00
-- 104 | 4 | 60.00
SELECT
customer_name,
order_total,
ROUND(order_total * CASE tier
WHEN 'gold' THEN 0.15
WHEN 'silver' THEN 0.10
WHEN 'bronze' THEN 0.05
ELSE 0
END, 2) AS discount
FROM customers c
JOIN orders o ON c.id = o.customer_id
ORDER BY o.id;
-- Output:
-- customer_name | order_total | discount
-- --------------+-------------+---------
-- Maya Brooks | 200.00 | 30.00
-- Leo Martin | 150.00 | 15.00
-- Ava Kim | 80.00 | 4.00
-- Noah Price | 60.00 | 0.00
Pivoter les ventes mensuelles en colonnes
Un SUM(CASE ...) par mois transforme les lignes de ventes en une colonne par mois :
-- Input: sales
-- product_category | sale_date | amount
-- -----------------+------------+-------
-- Books | 2026-01-12 | 40.00
-- Games | 2026-01-20 | 60.00
-- Books | 2026-02-03 | 25.00
-- Books | 2026-03-15 | 30.00
-- Games | 2026-03-28 | 75.00
SELECT
product_category,
SUM(CASE WHEN EXTRACT(MONTH FROM sale_date) = 1 THEN amount ELSE 0 END) AS jan_sales,
SUM(CASE WHEN EXTRACT(MONTH FROM sale_date) = 2 THEN amount ELSE 0 END) AS feb_sales,
SUM(CASE WHEN EXTRACT(MONTH FROM sale_date) = 3 THEN amount ELSE 0 END) AS mar_sales
FROM sales
GROUP BY product_category
ORDER BY product_category;
-- Output:
-- product_category | jan_sales | feb_sales | mar_sales
-- -----------------+-----------+-----------+----------
-- Books | 40.00 | 25.00 | 30.00
-- Games | 60.00 | 0 | 75.00
Dans SQL Server, utilise MONTH(sale_date) = 1 au lieu de EXTRACT ; dans SQLite, utilise strftime('%m', sale_date) = '01'.
Distinguer les valeurs manquantes des valeurs vides
Les données importées contiennent souvent à la fois des NULL et des chaînes vides. CASE peut étiqueter chacun pour que tu saches quoi nettoyer :
-- Input: users
-- id | middle_name
-- ---+------------
-- 1 | Rose
-- 2 |
-- 3 | NULL
SELECT
id,
CASE
WHEN middle_name IS NULL THEN 'Missing'
WHEN middle_name = '' THEN 'Empty'
ELSE middle_name
END AS middle_name
FROM users;
-- Output:
-- id | middle_name
-- ---+------------
-- 1 | Rose
-- 2 | Empty
-- 3 | Missing
Mettre les produits phares en premier
Attribue une position de tri à chaque catégorie, puis trie par nom à l’intérieur :
-- Input: products
-- product_name | category
-- -------------+------------
-- Wool Scarf | Sale
-- Desk Lamp | Featured
-- Bike Helmet | Clearance
-- Smart Watch | New Arrival
-- Air Fryer | Featured
SELECT product_name, category
FROM products
ORDER BY
CASE category
WHEN 'Featured' THEN 1
WHEN 'New Arrival' THEN 2
WHEN 'Sale' THEN 3
ELSE 4
END,
product_name;
-- Output:
-- product_name | category
-- -------------+------------
-- Air Fryer | Featured
-- Desk Lamp | Featured
-- Smart Watch | New Arrival
-- Wool Scarf | Sale
-- Bike Helmet | Clearance
Pour aller plus loin avec CASE
Sur ce blog :
- Guide SQL COALESCE : la façon rapide de prévoir un repli quand une valeur est NULL
- Guide des tableaux croisés en SQL : CASE dans SUM et AVG pour transformer des lignes en colonnes
- Guide SQL ORDER BY : le tri, y compris les ordres personnalisés
- Guide SQL GROUP BY : le regroupement sur lequel reposent les comptages et totaux conditionnels
- Guide SQL « différent de » : pourquoi les comparaisons avec NULL ne correspondent jamais
Documentation officielle :
Beekeeper Studio est une interface de base de données gratuite & open source
Le meilleur outil de requêtes & éditeur SQL que j’aie jamais utilisé. Il m’offre tout ce dont j’ai besoin pour gérer ma base de données. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio est rapide, intuitif et facile à utiliser. Beekeeper prend en charge plein de bases de données et fonctionne parfaitement sous Windows, Mac et Linux.
Ce que les utilisateurs disent de Beekeeper Studio
« Beekeeper Studio a complètement remplacé mon ancien workflow SQL. Il est rapide, intuitif, et rend le travail sur les bases de données à nouveau agréable. »
« J’ai essayé beaucoup de clients de base de données, mais Beekeeper trouve l’équilibre parfait entre fonctionnalités et simplicité. Ça marche, tout simplement. »