Vai al contenuto
eLearner.app
Modulo 7 · Lezione 3 di 427/57 nel corso~12 min
Lezioni del modulo (3/4)

LAG, LEAD e running totals

LAG e LEAD sono due window function speciali che ti danno accesso a altre righe della stessa partizione: la riga precedente (LAG) o successiva (LEAD) secondo l'ORDER BY della finestra. Sono lo strumento di elezione per confronti riga-su-riga (delta, variazioni, intervalli) e — combinati con SUM/AVG/COUNT OVER — per i running totals.

LAG: la riga precedente

SQL
LAG(colonna)            OVER (PARTITION BY p ORDER BY o)
LAG(colonna, n)         OVER (PARTITION BY p ORDER BY o)   -- n righe indietro
LAG(colonna, n, default) OVER (PARTITION BY p ORDER BY o)  -- default se non c'è

Esempio: per ogni ordine, "giorni dal precedente ordine dello stesso cliente":

SQL
SELECT id,
       customer_id,
       ordered_at,
       ordered_at - LAG(ordered_at) OVER (
         PARTITION BY customer_id ORDER BY ordered_at
       ) AS since_previous_order
FROM   orders
ORDER BY customer_id, ordered_at;

Il primo ordine di ogni cliente ha since_previous_order = NULL perché non esiste un "precedente" nella partizione.

LEAD: la riga successiva

Specchio di LAG. Tipico: "tempo fino al prossimo evento", "differenza con la versione successiva".

SQL
SELECT id, ordered_at,
       LEAD(ordered_at) OVER (PARTITION BY customer_id ORDER BY ordered_at)
         - ordered_at AS to_next
FROM   orders;

Running totals: aggregati con OVER

Le funzioni aggregate (SUM, AVG, COUNT, MAX, MIN) diventano cumulative quando combinate con OVER (… ORDER BY …):

SQL
SELECT order_id,
       total,
       SUM(total) OVER (
         PARTITION BY customer_id
         ORDER BY     ordered_at
       ) AS running_total
FROM   …;

Per ogni riga la SUM calcola la somma di tutte le righe della partizione fino a quel punto, secondo l'ORDER BY della finestra. Il risultato è il classico "saldo progressivo".

Prova tu

Esercizio#sql.m7.l3.e1
Tentativi: 0Caricamento…

Per ogni ordine mostra id, customer_id, ordered_at e una colonna days_from_previous che è il numero di giorni interi (con FLOOR) fra l'ordine corrente e il precedente dello stesso cliente, ordinati per ordered_at. NULL se non c'è precedente. Ordina per customer_id e ordered_at.

Caricamento editor…
Mostra suggerimento

LAG(ordered_at) OVER (PARTITION BY customer_id ORDER BY ordered_at) restituisce il timestamp dell'ordine precedente del cliente. Sottrai per ottenere un INTERVAL, poi converti in giorni.

Soluzione disponibile dopo 3 tentativi

Esercizio di ripasso

Esercizio#sql.m7.l3.e2
Tentativi: 0Caricamento…

Per ogni ordine consegnato (status = 'delivered'), mostra id, customer_id, ordered_at, order_total (somma di quantity * unit_price delle sue righe) e running_total (running total dei totali per cliente, ordinato per ordered_at). Usa una CTE per il order_total. Ordina per customer_id e ordered_at.

Caricamento editor…
Mostra suggerimento

La CTE calcola il totale per ordine; la SUM OVER produce il cumulato per cliente nel tempo.

Soluzione disponibile dopo 3 tentativi