Aggregazione condizionale è utilizzata quando è necessario aggregare valori (ad esempio, somma o conteggio) secondo diverse condizioni all'interno di un'unica query. Storicamente, per raggiungere tali obiettivi, gli sviluppatori SQL dovevano scrivere molteplici sottoquery o fare join e raggruppamenti separati per ciascuna categoria, il che portava a codice meno leggibile e meno performante.
Il problema risiedeva nella difficoltà di calcolare simultaneamente più aggregati con condizioni diverse—ogni aggregato singolo richiede generalmente filtraggio e l'applicazione semplice di SUM() o COUNT() non considera la necessaria condizione all'interno della funzione aggregata.
Soluzione — utilizzare la costruzione CASE all'interno della funzione aggregata, che consente di "separare" gli aggregati secondo diverse condizioni al volo, senza dover ricorrere a molteplici unioni:
Esempio di codice:
SELECT department, SUM(CASE WHEN status = 'approved' THEN amount ELSE 0 END) AS approved_sum, SUM(CASE WHEN status = 'pending' THEN amount ELSE 0 END) AS pending_sum, COUNT(CASE WHEN status = 'rejected' THEN 1 END) AS rejected_count FROM payments GROUP BY department;
Caratteristiche chiave:
È possibile fare a meno della costruzione CASE per aggregazione condizionale?
La risposta errata è utilizzare WHERE nella query direttamente insieme alla funzione aggregata. In realtà, WHERE filtra le righe prima dell'aggregazione, e non all'interno di ciascuna colonna aggregata.
Esempio di codice (metodo errato):
SELECT COUNT(*) FROM payments WHERE status = 'approved'; SELECT COUNT(*) FROM payments WHERE status = 'pending';
Queste query non possono essere unite in un'unica stringa di risultato secondo condizioni diverse senza CASE.
Cosa succede se si utilizza NULL all'interno dell'espressione condizionale?
Se CASE non restituisce un valore alternativo, per impostazione predefinita sarà NULL, e la funzione aggregata ignorerà NULL.
Esempio di codice:
SUM(CASE WHEN status = 'approved' THEN amount END) -- Se lo status non è 'approved', allora NULL e la riga viene ignorata in SUM
È possibile utilizzare IF invece di CASE?
In alcuni dialetti SQL (ad esempio, MySQL) è possibile, ma tale codice diventa non portabile tra diversi database. Negli interrogazioni universali utilizzare sempre CASE.
Un analista ha tentato di contare le somme per ciascun stato, scrivendo diverse sottoquery separate. Il report esterno è diventato complesso, e l'aggiunta di nuovi stati ha richiesto la riscrittura del codice ogni volta.
Pro:
Un sviluppatore ha utilizzato CASE in un'unica query generale, creando un report universale con la possibilità di espandersi per nuovi stati tramite una semplice modifica di un'unica query.
Pro: