In questo articolo vedremo vari esempi di utilizzo dell’espressione CASE WHEN con il linguaggio SQL, facendo riferimento in particolare al database SQL Server.
Utilizzare CASE WHEN all’interno della SELECT
La sintassi generale dell’istruzione CASE WHEN è la seguente
CASE WHEN <condizione 1> THEN <risultato 1>
WHEN <condizione 2> THEN <risultato 2>
...
ELSE <risultato n>
END
Ma studiamola meglio con alcuni esempi pratici. Nell’ambito del linguaggio SQL, l’utilizzo più comune dell’espressione CASE WHEN è all’interno della clausola SELECT, per arricchire con dei calcoli le informazioni presenti all’interno del database. Supponiamo ad esempio di voler calcolare l’informazione se il cliente abbia più o meno di 18 anni, a partire dalla colonna età della tabella Clienti. Scriveremo allora:
SELECT Nome,
Cognome,
Eta,
CASE WHEN Eta >= 18 THEN '18+'
WHEN Eta < 18 THEN '18-'
ELSE NULL
END AS Tipologia_cliente
FROM Clienti;
In generale l’istruzione ELSE non è obbligatoria. La sua omissione è equivalente a specificare ELSE NULL, tuttavia il mio consiglio è di scriverla sempre esplicitamente, in modo da rendere più chiaro il nostro codice. Ricordiamoci inoltre di fare sempre attenzione a come le varie condizioni gestiscono la presenza di NULL. Ad esempio, la prossima query non è del tutto equivalente a quella precedente:
SELECT ...,
CASE WHEN Eta >= 18 THEN '18+'
ELSE '18-'
END AS Tipologia_cliente
...
Infatti in essa, se nella colonna Eta ci fosse un NULL, l’output sarebbe comunque “18-“. In generale dopo l’istruzione WHEN possiamo scrivere condizioni complesse a piacere, bisogna comunque tenere a mente che esse sono verificate nello stesso ordine con cui sono scritte. Ad esempio per questa espressione
CASE WHEN Eta >= 18 THEN '18+' WHEN Eta >= 25 THEN '25+' END
l’output relativo al valore 27 è comunque pari a “18+” perché è la prima condizione a essere verificata tra le due scritte.
CASE WHEN in una posizione generica della query
La CASE WHEN può essere utilizzata in praticamente tutte le clausole di una query SQL. Ad esempio potrei usare un’espressione simile a quella del paragrafo precedente anche all’interno di una GROUP BY, per calcolare la distribuzione di una particolare colonna:
SELECT
CASE WHEN Importo >= 0 AND Importo < 1000 THEN 'Basso'
WHEN Importo >= 1000 AND Importo < 2000 THEN 'Medio'
WHEN Importo >= 2000 THEN 'Alto'
ELSE NULL
END AS Tipologia_cliente,
COUNT(*) AS Numero
FROM Clienti
GROUP BY
CASE WHEN Importo >= 0 AND Importo < 1000 THEN 'Basso'
WHEN Importo >= 1000 AND Importo < 2000 THEN 'Medio'
WHEN Importo >= 2000 THEN 'Alto'
ELSE NULL
END;
La CASE WHEN può risultare molto utile anche all’interno di una clausola ORDER BY, ad esempio se voglio creare delle eccezioni nell’ordinamento di una colonna. Consideriamo ad esempio la seguente istruzione:
ORDER BY
CASE WHEN IdCliente = 7 THEN 1
ELSE 2
END,
Nome
Visualizzeremo al primo posto il cliente con codice 7, seguito da tutti gli altri in ordine alfabetico di nome.
CASE WHEN all’interno di funzioni di aggregazione
Combinando correttamente la CASE WHEN con funzioni di aggregazione come COUNT e SUM possiamo scrivere in modo efficiente alcune query che richiedono di verificare varie tipologie di condizioni. Supponiamo ad esempio che tutte le fatture di acquisto e vendita siano salvate nella stessa tabella con un importo positivo, con l’indicazione della tipologia “A” o “V”. Per calcolare la differenza tra vendite e acquisti per ogni anno potrei scrivere:
SELECT
YEAR(DataFattura) AS Anno
SUM(CASE WHEN tipologia = 'V' THEN Importo
WHEN Tipologia = 'A' THEN -1*Importo
ELSE NULL
END) AS Utile
FROM Fatture
GROUP BY YEAR(DataFattura);
In modo analogo è possibile eseguire il pivot dei dati con il linguaggio SQL, come descrivo più in dettaglio in questo mio articolo https://www.yimp.it/convertire-righe-in-colonne-con-lsql/
Tipo dell’espressione in output
Ragioniamo ora su una caratteristica molto importante dell’espressione CASE WHEN: il tipo risultante. Bisogna sottolineare che quanto detto in questo paragrafo vale su SQL Server, ma può essere differente su altri database, come ad esempio MySQL.
Su SQL Server il tipo associato a una CASE WHEN è quello con precedenza maggiore rispetto a tutti i possibili risultati, secondo quanto indicato nella documentazione ufficiale https://learn.microsoft.com/it-it/sql/t-sql/data-types/data-type-precedence-transact-sql?view=sql-server-ver16.
Guardiamo ad esempio questo codice SQL:
CASE WHEN Nome = 'Nicola' THEN 'N'
WHEN Nome = 'Giovanni' THEN 1
ELSE NULL
END
In questo caso i possibili valori sono:
- il varchar ‘N’;
- l’intero 1;
- un NULL.
In questo caso il tipo con maggiore precedenza è l’intero e di conseguenza tale sarà anche il tipo dell’output di CASE WHEN. Di conseguenza, se ci fosse una riga con un valore come “Nicola” nella colonna Nome, la query su SQL Server causerebbe un errore di conversione (ma non su MySQL).
Per gli stessi motivi il codice seguente restituisce sempre un errore su SQL Server, a prescindere dal fatto che la condizione scritta nel ramo ELSE non sarà mai valutata
SELECT
CASE WHEN 1 = 1 THEN 'a'
ELSE 1
END
Su MySQL la query precedente restituisce, invece, la stringa “a“.
Continua a imparare
- Segui la lezione successiva sulle Window Function
- Torna all’indice delle lezioni
- Visita la pagina del mio video corso online di SQL