← Torna indietro alla pagina principale del Blog

Uso di CASE per estrarre con SQL dal database dati utili ad analisi statistiche

Tag: SQL, Coding, Database, Riflessioni e appunti

Pubblicato il 3 marzo 2022

Uso di CASE per estrarre con SQL dal database dati utili ad analisi statistiche

In questo breve articolo si descrive l’uso dell’asserzione CASE del linguaggio SQL, offrendo un caso di studio archeologico.

CASE è un costrutto molto potente e spesso trascurato del linguaggio SQL, che permette di attraversare varie possibili condizioni fornite e restituisce un valore quando la prima condizione viene soddisfatta, esattamente come le asserzioni if-then-else in molti altri linguaggi di programmazione.

Quando una condizione si verifica, il ciclo si fermerà e restituirà il risultato corrispondente fornito. Se nessuna condizione viene soddisfatta, verrà restituito il valore contenuto nalla clausola ELSE.

Se, infine, la parte ELSE non viene fornita, verrà restituito il valore NULL (che è diverso dalla stringa 'NULL').

La sintassi di CASE è la seguente:

CASE
WHEN consizione_1 THEN "qualcosa"
WHEN condizione_2 THEN "qualcos'altro"
...
ELSE "Valore di default"
END

Un esempio vale più di mille spiegazioni, ecco allora che nei prossimi paragrafi introduco un caso di studio reale, lo stesso che mi ha fatto scoprire questa funzione.

In concreto, stavo lavorando su una banca dati relativa alla necropoli romana della città romana di Suasa e avevo bisogno di estrarre alcuni dati per creare dei grafici piuttosto semplici. In particolare, avevo bisogno di estrarre in maniera veloce il totale delle tombe divise per fase, e all’interno di ogna fase il totale delle tombe a inumazione e di quelle a cremazione. La necessità finale era quella di ottenere un grafico a barre, che per ogni fase visualizzasse il numero totale di tombe per ciascuno dei due riti.

Di seguito, fornisco un estratto della struttura della tabella di riferimento dalla quale estrarre questa informazione. La tabella è più complessa, ma estraggo qui solo le colonne che ci interessano.

Query:

SELECT id,
nome,
rito,
fase
FROM suasa__tombe;

Risultato:

idnumero tombaritofase
1503cremazione10
2511cremazione8
4501cremazione11
5502cremazione11
6508cremazione10
7509cremazione10
8512inumazione7
10514cremazione10
11510cremazione10a
18518cremazione7
19519cremazione7
20520cremazione7
21521cremazione10
22522cremazione7
23524cremazione7
24523cremazione10
25528cremazione7
26530cremazione11
27533cremazione7
28531cremazione10
29529cremazione11
30526cremazione7
32534cremazione10
36535cremazione6
37537cremazione10b
38538inumazione12
39543cremazione10
40542cremazione10
41540cremazione10a
42544cremazione10
43539cremazione10b
44541inumazione12
45545inumazione12
46547cremazione10
48549cremazione10
49548cremazione10
50552cremazione10a
52550cremazione10
53555cremazione7
54556cremazione7
56557cremazione10
57558cremazione10
59554inumazione12
60560inumazione12
61561cremazione10
62567cremazione10a
63563inumazione12
64568cremazione10a
65566inumazione10a
66565inumazione12
67571cremazione9
68569cremazione10a
69570cremazione10a
70572cremazione9
71562inumazione12
72564inumazione12
73573cremazione11
74574cremazione11
75576cremazione11
76575cremazione11
77577cremazione11
78578cremazione10a
79579cremazione11
80580inumazione11
81581cremazione10b
82584cremazione10
83587cremazione10
84589inumazione10b
87582cremazione10b
88585cremazione11
89586cremazione11
90590cremazione9
91591cremazione9
92601cremazione9
93603cremazione9
95583cremazione9
96593cremazione10
97594cremazione10
98602cremazione7
99607cremazione7
100599cremazione9
101596inumazione10b
102598cremazione9
103595cremazione10b
104597inumazione10b
105600cremazione8
106606inumazione8
107608cremazione10a
108605cremazione9

Ecco allora la query per estrarre i dati che servono:

SELECT SUM(CASE WHEN rito = 'inumazione' THEN 1 ELSE 0 END) AS inumazioni,
SUM(CASE WHEN rito = 'cremazione' THEN 1 ELSE 0 END) AS cremazioni,
fase
FROM suasa__tombe
GROUP BY fase;

Ed ecco infine i risultati della query, pronti per essere trasformati in un grafico:

inumazionicremazionifase
02210
1910a
3510b
11211
9012
016
1127
128
0109

In questo caso stiamo usando l’asserzione CASE nella definizione delle colonne e lo stiamo usando insieme alla funzione SUM, che calcola le somme.

In dettaglio, SUM(CASE WHEN rito = 'inumazione' THEN 1 ELSE 0 END) AS inumazioni e la definizione di una colonna alla quale viene attribuita l’etichetta o l’alias inumazioni, come da asserzione AS (segui questo collegamento per avere più informazioni su AS), all’unico fine di facilitare la lettura dei dati in uscita.

La colonna contiene una somma, le cui elementi vengono definiti da CASE. Per ogni riga della banca dati verrà valutata se l’espressione booleana rito = 'inumazione' risulta vera o false, in altre parole verrà valutato se il campo rito contiene esattamente il valore inumazione. Se la risposta è positiva (valore booleano VERO), allora (THEN) viene restituito alla funzione somma in numero 1 (al conteggio delle inumazioni viene aggiunto una unità), altrimenti (ELSE) viene restituito 0 (al conteggio delle inumazioni non viene in sostanza aggiunto nulla).

Lo stesso discorso vale per la seconda colonna, definita come: SUM(CASE WHEN rito = 'cremazione' THEN 1 ELSE 0 END) AS cremazioni, cambia solo l’etichetta e naturalmente il valore di riferimento del campo rito.

Abbiamo parlato sopra di conteggio di valori, per ogni riga perché in questa query stiamo raggruppando valori, e nello specifico li stiamo raggruppando per il campo fase, com’è chiara dall’ultima parte della query principale GROUP BY fase, che aggiunge un principio di aggregazione (segui questo collegamento per avere più informazioni su GROUP BY).

Con CASE si possono usare tutti gli operatori SQL (es. =, <, >, <=, >=, LIKE, ecc.) ed è possibile concatenare più condizioni usando i soliti AND o OR. La cosa importante è che l’espressione tra WHEN e THEN restitusca sempre un valore booleando di VERO o FALSO. Il caso esposto sopra era piuttosto semplice, ma è possibile prevedere anche più asserzioni WHEN...THEN.

Riferimenti