Immagina: stai tenendo d’occhio i ricavi della tua azienda, le vendite di un e-commerce o magari semplicemente analizzi le tue spese annuali. Non ti basta vedere ricavi o spese per ogni mese, ma vuoi anche capire come si accumulano mese dopo mese.
Le classiche funzioni di aggregazione (GROUP BY) qui non bastano — raggruppano i dati e ti danno una riga per gruppo. Ma se vuoi vedere ogni mese e allo stesso tempo calcolare la somma cumulativa? Ecco dove SUM() insieme alle funzioni finestra ti salva la vita.
Basi dell’uso delle funzioni finestra per somme cumulative
Le funzioni finestra ti permettono di fare operazioni di aggregazione su finestre di dati. Così puoi, ad esempio, sommare valori su ogni riga senza perdere le altre righe. Niente più sacrifici per colpa di GROUP BY!
Sintassi di SUM() con funzione finestra
Ecco il template base per calcolare una somma cumulativa:
SELECT
column_name,
SUM(column_name) OVER (PARTITION BY partition_column ORDER BY order_column) AS cumulative_sum
FROM
table_name;
Qui:
SUM(column_name)— somma i valori.OVER()— definisce la finestra per il calcolo.PARTITION BY— divide i dati in gruppi (opzionale).ORDER BY— ordina le righe dentro la finestra.
Esempio: ricavo cumulativo per mese
Immagina una tabella dei tuoi ricavi:
| mese | ricavo |
|---|---|
| 2023-01 | 1000 |
| 2023-02 | 1500 |
| 2023-03 | 2000 |
Vogliamo vedere il ricavo di ogni mese e il totale cumulativo. Proviamo a scrivere una query SQL:
SELECT
mese,
ricavo,
SUM(ricavo) OVER (ORDER BY mese) AS ricavo_cumulativo
FROM
ricavi;
Risultato:
| mese | ricavo | ricavo_cumulativo |
|---|---|---|
| 2023-01 | 1000 | 1000 |
| 2023-02 | 1500 | 2500 |
| 2023-03 | 2000 | 4500 |
Cosa succede qui:
ORDER BY mesedentroOVER()dice a PostgreSQL di considerare le righe in ordine cronologico.- Per ogni riga la somma viene calcolata includendo tutte le righe precedenti (e quella attuale).
Pensaci bene: per la prima riga SUM() fa la somma solo della prima riga, per la seconda — delle prime due, per la terza — delle prime tre. Ecco perché l’ordine dei mesi è fondamentale!
Esempio: ricavo cumulativo per regione
Se avessi una tabella delle vendite per regione, una parte potrebbe essere così:
| regione | mese | ricavo |
|---|---|---|
| Settentrionale | 2023-01 | 1000 |
| Settentrionale | 2023-02 | 1500 |
| Meridionale | 2023-01 | 2000 |
| Meridionale | 2023-02 | 2500 |
Ora vogliamo calcolare il ricavo cumulativo separatamente per ogni regione:
SELECT
regione,
mese,
ricavo,
SUM(ricavo) OVER (PARTITION BY regione ORDER BY mese) AS ricavo_cumulativo
FROM
vendite;
Il risultato sarà così:
| regione | mese | ricavo | ricavo_cumulativo |
|---|---|---|---|
| Settentrionale | 2023-01 | 1000 | 1000 |
| Settentrionale | 2023-02 | 1500 | 2500 |
| Meridionale | 2023-01 | 2000 | 2000 |
| Meridionale | 2023-02 | 2500 | 4500 |
Ora ogni regione viene analizzata separatamente (PARTITION BY regione), ma dentro la regione le righe sono ordinate per tempo (ORDER BY mese).
Media mobile (AVG())
Ok, le somme cumulative sono top, ma se vuoi analizzare i trend, tipo negli ultimi 3 mesi? Qui entra in gioco la media mobile.
Esempio: media mobile dei ricavi
Lavoriamo di nuovo con la tabella ricavi, ecco i dati:
| mese | ricavo |
|---|---|
| 2023-01 | 1000 |
| 2023-02 | 1500 |
| 2023-03 | 2000 |
| 2023-04 | 2500 |
Query per calcolare la media mobile su 3 mesi:
SELECT
mese,
ricavo,
AVG(ricavo) OVER (
ORDER BY mese
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS media_mobile
FROM
ricavi;
Risultato:
| mese | ricavo | media_mobile |
|---|---|---|
| 2023-01 | 1000 | 1000 |
| 2023-02 | 1500 | 1250 |
| 2023-03 | 2000 | 1500 |
| 2023-04 | 2500 | 2000 |
Spiegazione:
ROWS BETWEEN 2 PRECEDING AND CURRENT ROWdice a PostgreSQL di guardare la riga attuale e le due precedenti per calcolare la media.- Così per ogni mese vedi la media dei ricavi degli ultimi 3 mesi.
Cioè, per ogni riga definiamo una finestra di 3 righe: quella attuale e le due precedenti. Poi calcoliamo la media su queste. Super comodo.
Come funziona ORDER BY e il suo impatto
Le funzioni finestra dipendono dall’ordine giusto delle righe. Se l’ordine è sbagliato (o manca), i risultati possono essere strani.
Esempio: errori senza ORDER BY
Se togliamo ORDER BY da OVER(), invece della somma cumulativa otteniamo la somma totale su tutte le righe per ogni riga:
SELECT
mese,
ricavo,
SUM(ricavo) OVER () AS somma_cumulativa_sbagliata
FROM
ricavi;
Risultato:
| mese | ricavo | sommacumulativasbagliata |
|---|---|---|
| 2023-01 | 1000 | 7000 |
| 2023-02 | 1500 | 7000 |
| 2023-03 | 2000 | 7000 |
| 2023-04 | 2500 | 7000 |
Le righe non sono ordinate, e invece della somma cumulativa la funzione fa la somma totale su tutte le righe senza distinzioni.
Casi d’uso reali
Analisi dei ricavi:
- Le somme cumulative ti fanno vedere come crescono le vendite o i ricavi dell’azienda.
- La media mobile ti aiuta a vedere il trend “pulito” senza rumore.
Modellazione finanziaria:
Banche e aziende finanziarie usano le funzioni finestra per analizzare pagamenti, crescita dei debiti e altre metriche.
Costruzione di serie temporali:
Dati temporali come numero di utenti online, visualizzazioni di pagina, fatturato ecc. sono perfetti da analizzare con SUM() e AVG().
GO TO FULL VERSION