CASE è l'if/else di SQL
CASE è il modo per inserire logica condizionale dentro una query. Scorre i rami WHEN in ordine, sceglie il primo che corrisponde e restituisce il valore dopo THEN. Se non corrisponde nulla, restituisce il valore di ELSE, oppure NULL se non l'hai scritto.
La parola importante è espressione. CASE produce un valore, quindi può stare ovunque sia ammesso un valore: una colonna della SELECT, una chiave di ORDER BY, il lato destro di un confronto, l'argomento di una funzione.
Questa è la forma completa: CASE, uno o più WHEN ... THEN ..., un ELSE facoltativo, poi END. END è obbligatorio: dimenticarlo è l'errore di battitura più comune.
Un esempio realistico
Mettiamo che tu abbia una tabella di ordini e voglia etichettare ogni riga in base alla dimensione. Creane una piccola al volo per poter eseguire la query:
I rami vengono controllati dall'alto verso il basso. Vince la prima corrispondenza, quindi ordinali dal più specifico al più generale. ELSE cattura tutto ciò che non ha trovato corrispondenza: senza di esso, 1200.00 tornerebbe come NULL invece di 'large'.
Con condizioni contro semplice
Quella che hai visto sopra è la forma con condizioni (searched): ogni WHEN ha la sua condizione booleana. Esiste una forma più breve quando confronti un'espressione con diverse costanti, la forma semplice:
L'espressione dopo CASE viene valutata una volta e confrontata con = rispetto a ogni valore di WHEN. È più pulita quando fai ricerche per uguaglianza su una sola colonna.
Un'insidia: il CASE semplice usa =, e in SQL NULL = NULL non è vero. Se status può essere NULL, i rami 'A'/'B'/'C' non corrisponderanno e finirai in ELSE. Per gestire NULL in modo esplicito, passa alla forma con condizioni e usa WHEN status IS NULL THEN ....
CASE in ORDER BY
ORDER BY accetta qualsiasi espressione, quindi CASE funziona benissimo anche lì. È utile quando vuoi un ordinamento personalizzato che non segue l'ordine alfabetico o numerico:
In ordine alfabetico 'high' < 'low' < 'medium', che non serve a nulla per decidere le priorità. Mappare ogni priorità su un numero con CASE ti dà l'ordine che vuoi davvero. Il , id finale risolve i pari merito in modo stabile.
CASE in WHERE
Puoi mettere CASE dentro WHERE, ma la maggior parte delle volte non serve: una catena di AND/OR è più chiara. Il suo punto di forza è quando la condizione stessa dipende da un altro valore:
Gli articoli in saldo si qualificano sotto 20, quelli normali sotto 30. La soglia stessa è condizionale. Senza CASE dovresti scrivere (on_sale = 1 AND price < 20) OR (on_sale = 0 AND price < 30): stesso risultato, più rumore.
CASE dentro le aggregazioni
È qui che CASE si guadagna da vivere. Combinalo con SUM o COUNT per calcolare totali su un sottoinsieme di righe in un solo passaggio: l'equivalente SQL di "conta quanti di questi corrispondono":
Il CASE restituisce 1 per le righe che corrispondono e 0 per le altre, così SUM diventa un conteggio condizionale. Lo stesso trucco funziona per il fatturato: restituisci total sulle righe che corrispondono e 0 altrove. Una sola scansione della tabella, diverse aggregazioni condizionali.
IIF: la scorciatoia a due rami
Per una singola condizione con due esiti, SQLite ha IIF(cond, when_true, when_false). È solo una scorciatoia per CASE WHEN cond THEN when_true ELSE when_false END:
Usa IIF quando la logica è binaria e si legge meglio su una riga. Passa a CASE quando hai tre o più rami, devi gestire NULL separatamente o vuoi l'ordine a cascata di più clausole WHEN.
Insidie da conoscere
Alcune cose che fanno inciampare:
- Dimenticare
END.CASEapre un blocco;ENDlo chiude. SQLite ti darà un errore di parsing ben dopo il punto in cui hai sbagliato. - Nessun
ELSEsignificaNULL. Se nessuno dei ramiWHENcorrisponde e hai omessoELSE, il risultato èNULL. A volte è quello che vuoi; di solito no. - L'ordine dei rami conta. Nella forma con condizioni vince il primo
WHENche corrisponde. MettereWHEN total < 500prima diWHEN total < 100rende irraggiungibile il secondo ramo. - Tipi misti. Ogni ramo può restituire un tipo diverso e SQLite non si lamenta, ma il codice a valle potrebbe farlo. Cerca di far restituire a tutti i rami tipi compatibili (tutti testo, tutti numerici).
CASEsemplice eNULL. Come detto: la forma semplice usa=, che non corrisponde mai aNULL. Usa la forma con condizioni quando ci sono dei null in gioco.
Prossimo passo: le funzioni sulle stringhe
CASE ti permette di ramificare sui valori; il prossimo capitolo inizia a trasformare i valori. Le funzioni sulle stringhe, UPPER, LOWER, SUBSTR, REPLACE, i pattern di LIKE, si occupano del lavoro quotidiano di pulizia e riformattazione delle colonne di testo. Sono il prossimo argomento.
Domande frequenti
Cos'è un'espressione CASE in SQLite?
Un'espressione CASE è la versione SQL di if/else: valuta delle condizioni e restituisce un valore. È un'espressione, non un'istruzione, quindi puoi usarla ovunque sia ammesso un valore: in SELECT, WHERE, ORDER BY, UPDATE, persino dentro le aggregazioni. Ogni ramo ha la forma WHEN condition THEN value, con un ELSE facoltativo alla fine.
Che differenza c'è tra CASE semplice e CASE con condizioni in SQLite?
Un CASE semplice confronta un'espressione con diversi valori: CASE status WHEN 'A' THEN ... WHEN 'B' THEN ... END. Un CASE con condizioni valuta un'espressione booleana separata per ogni ramo: CASE WHEN price > 100 THEN ... WHEN qty = 0 THEN ... END. La forma con condizioni è più flessibile: può combinare liberamente colonne, operatori e controlli su NULL.
Quando conviene usare IIF invece di CASE in SQLite?
IIF(cond, a, b) è una scorciatoia per CASE WHEN cond THEN a ELSE b END. Usa IIF per logiche a due rami, dove si legge meglio. Passa a CASE quando hai tre o più rami, vuoi un ordine di valutazione a cascata o devi gestire NULL in modo esplicito con WHEN col IS NULL.