Come usare l’espressione CASE WHEN su SQL Server

case when in SQL

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

Torna in alto
Torna su