CASE aggiunge la logica if/then/else a una query SQL: controlla una lista di condizioni e restituisce il risultato della prima che è vera. Gli esempi funzionano in PostgreSQL, MySQL, SQLite e SQL Server.
Come usare CASE
Elenca le coppie WHEN condition THEN result tra CASE e END. CASE restituisce il risultato della prima condizione vera, oppure il valore di ELSE se nessuna lo è:
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
Quando ogni condizione verifica l'uguaglianza con lo stesso valore, la forma “semplice”, più breve, indica quel valore una sola volta:
SELECT
CASE 'amber'
WHEN 'green' THEN 'Go'
WHEN 'amber' THEN 'Slow down'
WHEN 'red' THEN 'Stop'
ELSE 'Unknown'
END;
-- Output: Slow down
In una query reale le condizioni verificano le colonne, e CASE aggiunge una nuova colonna al risultato:
-- 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
Regole da conoscere
-
Vince la prima condizione vera. Le condizioni vengono controllate dall'alto verso il basso, quindi metti per prima la più restrittiva. Sopra,
100.00è Medium perchéamount < 100è falso eamount < 500è vero. Nell'ordine sbagliato, gli importi piccoli non raggiungono mai il loro ramo:
SELECT
CASE
WHEN 45 < 500 THEN 'Medium'
WHEN 45 < 100 THEN 'Small' -- can never win
ELSE 'Large'
END;
-- Output: Medium
- Senza ELSE, se nulla corrisponde ottieni NULL.
SELECT CASE WHEN 72 >= 90 THEN 'Hot' END;
-- Output: NULL
-
Verifica NULL con IS NULL.
NULL = NULLnon è vero, quindi la forma semplice non può trovare un NULL. Usa la forma con condizioni:
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
- Ogni risultato deve avere un tipo compatibile. Mescolare un numero e del testo nello stesso CASE dà errore in PostgreSQL e SQL Server, quindi converti il numero:
-- 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
Sintassi alternativa
Per una singola condizione, troverai anche una funzione più breve:
-- MySQL
SELECT IF(72 >= 60, 'Mild', 'Cold');
-- Output: Mild
-- SQL Server and SQLite
SELECT IIF(72 >= 60, 'Mild', 'Cold');
-- Output: Mild
Altre due funzioni sono abbreviazioni di espressioni CASE comuni. COALESCE(nickname, name) equivale a CASE WHEN nickname IS NOT NULL THEN nickname ELSE name END, e NULLIF(a, b) equivale a CASE WHEN a = b THEN NULL ELSE a END. Per la prima, leggi la guida a SQL COALESCE.
MySQL ha anche un'istruzione CASE per le stored procedure, che termina con END CASE. Questo articolo tratta l'espressione CASE che usi nelle query.
Quando usare CASE?
CASE è un'espressione, quindi funziona ovunque possa stare un valore: nella lista del SELECT, in ORDER BY e GROUP BY e dentro le funzioni di aggregazione. Funziona anche in WHERE, ma lì AND e OR di solito sono più chiari. La maggior parte degli usi rientra in uno di questi cinque.
Suddividere i numeri in fasce
Trasforma un numero in una fascia: livelli di prezzo, dimensioni degli ordini, fasce d'età, voti. Scrivi le condizioni da un estremo all'altro della scala, così la prima corrispondenza è quella giusta.
Tradurre codici in etichette
I database memorizzano codici brevi come 'A', 'ENG' o 'gold'; le persone vogliono parole. Un CASE semplice associa ogni codice a un'etichetta, o a un valore come una percentuale di sconto, ed ELSE cattura qualsiasi codice inatteso.
Contare o sommare solo alcune righe
Metti CASE dentro COUNT o SUM per contare o sommare solo le righe che soddisfano una condizione. COUNT(CASE WHEN ... THEN 1 END) funziona perché le righe senza corrispondenza danno NULL, che COUNT ignora. Un'aggregazione per condizione ti dà più totali affiancati: è così che si costruisce una tabella pivot in SQL.
Gestire i valori mancanti
Controlla le colonne per NULL in ordine di preferenza e restituisci un'etichetta quando sono tutte vuote. Per un semplice valore di ripiego, COALESCE è più breve. CASE è lo strumento giusto quando ogni tipo di lacuna richiede un risultato diverso.
Ordinare in modo personalizzato
L'ordine alfabetico e numerico non va bene per tutto: taglie di abbigliamento, priorità dei ticket, una lista con i prodotti in evidenza in cima. Un CASE in ORDER BY assegna a ogni valore la posizione che vuoi.
Esempi reali di CASE
Classificare i prodotti per reparto e prezzo
Un risultato può essere a sua volta un CASE, così ogni reparto ha le sue fasce di prezzo:
-- 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
Oltre due livelli, i CASE annidati diventano difficili da leggere. Di solito è più chiara una tabella di lookup da unire con una join.
Applicare uno sconto in base al livello del cliente
Ogni codice di livello corrisponde a una percentuale di sconto, e i clienti senza livello non ne ricevono:
-- 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
Trasformare le vendite mensili in colonne
Un SUM(CASE ...) per mese trasforma le righe di vendita in una colonna per ogni mese:
-- 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
In SQL Server, usa MONTH(sale_date) = 1 al posto di EXTRACT; in SQLite, usa strftime('%m', sale_date) = '01'.
Distinguere i valori mancanti da quelli vuoti
I dati importati spesso contengono sia NULL sia stringhe vuote. CASE può etichettarli in modo che tu sappia cosa ripulire:
-- 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
Mettere in cima i prodotti in evidenza
Assegna a ogni categoria una posizione di ordinamento, poi ordina per nome al suo interno:
-- 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
Approfondimenti su CASE
Su questo blog:
- Guida a SQL COALESCE: il modo rapido per avere un valore di ripiego quando un valore è NULL
- Guida alle tabelle pivot in SQL: CASE dentro SUM e AVG per trasformare righe in colonne
- Guida a SQL ORDER BY: ordinamento, inclusi gli ordini personalizzati
- Guida a SQL GROUP BY: il raggruppamento su cui si basano conteggi e totali condizionali
- Guida all'operatore diverso in SQL: perché i confronti con NULL non corrispondono mai
Documentazione ufficiale:
Beekeeper Studio è una GUI per database gratuita & open source
Il miglior strumento per query & editor SQL che abbia mai usato. Offre tutto ciò che mi serve per gestire il mio database. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio è veloce, intuitivo e facile da usare. Beekeeper supporta tantissimi database e funziona alla grande su Windows, Mac e Linux.
Cosa dicono gli utenti di Beekeeper Studio
"Beekeeper Studio ha sostituito completamente il mio vecchio flusso di lavoro SQL. È veloce, intuitivo e rende di nuovo piacevole lavorare con i database."
"Ho provato molte GUI per database, ma Beekeeper trova l'equilibrio perfetto tra funzionalità e semplicità. Funziona e basta."