Torna all'elenco degli articoli Articoli
Tempo di lettura: 8 minuti

Funzione SQL LAG()

La funzione LAG() - una delle funzioni finestra di SQL, è uno strumento importante per la pianificazione e l'analisi delle tendenze. In questo articolo vi mostrerò come includere la funzione SQL LAG() nelle vostre query utilizzando alcuni esempi reali.

Lefunzioni finestra diSQL , note anche come funzioni analitiche o funzioni OVER, aggiungono una nuova dimensione all'analisi dei dati. Permettono di includere aggregati o dati di altre righe accanto alla riga corrente.

La funzione LAG() consente di guardare indietro "attraverso la finestra" a una riga precedente e di includere i suoi dati accanto alla riga corrente. Una funzione simile, LEAD(), consente di guardare in avanti alle righe successive. Utilizzando le funzioni LEAD() e LAG(), è possibile includere facilmente nei report caratteristiche utili come i confronti anno per anno.

Se volete fare sul serio con l'analisi dei dati, potreste dare un'occhiata al corso LearnSQL.it'Window Functions (Funzioni Finestra) . Imparerete risolvendo oltre 200 esercizi interattivi guidati utilizzando un vero database a cui accederete tramite il vostro browser. Il corso richiede circa 20 ore; una volta terminato, potrete utilizzare le vostre nuove competenze per potenziare i vostri progetti di analisi dei dati.

Cosa fa la funzione LAG()?

Questa funzione consente di includere il valore di una colonna di una riga precedente accanto ai dati della riga corrente. È particolarmente utile per analizzare le tendenze nel tempo, come i confronti tra mesi e anni.

Può essere utilizzato anche per rispondere a diverse domande. Quanto è grande il divario tra i risultati medi della scuola A e quelli della scuola B? Quanto incide l'utilizzo di una materia prima diversa sulla durata di un componente?

Sintassi della funzione LAG()

Nella sua forma più semplice, la sintassi della funzione SQL LAG() è ...

LAG(column_1) OVER (ORDER BY column_2)

... dove:

  • column_1 è il nome della colonna che si vuole includere dalla riga precedente.
  • OVER indica che si sta utilizzando una funzione finestra; questa parola chiave è obbligatoria.
  • ORDER BY è obbligatoria anche quando si usa LAG(). La sequenza delle righe deve essere prevedibile, altrimenti la funzione non ha senso. Tuttavia, non è necessario che l'ordine scelto sia lo stesso del report finale.
  • column_2 è la colonna che si usa per ordinare le righe. È possibile specificare più di una colonna.

SQL mette in sequenza i dati utilizzando i valori della colonna_2. Per ogni riga, guarda indietro alla riga precedente di questa sequenza e recupera il valore della colonna_1. Questo valore viene incluso insieme a qualsiasi altro dato richiesto dalla riga corrente.

Esempio di base della funzione LAG()

Vediamo un semplice confronto mese per mese. Una tabella denominata monthly_sales contiene i seguenti dati:

yearmonthsales_qtysales_value
20231210007380
202418005620
202429426945
2024312701745
2024415202048
2024514001890

Se si volesse vedere le vendite del mese scorso insieme a quelle di questo mese, la query avrebbe il seguente aspetto:

SELECT 
  year, 
  month, 
  sales_value, 
  LAG(sales_value) OVER (ORDER BY year, month) AS last_month
FROM monthly_sales;

Il risultato è questo:

yearmonthsales_valuelast_month
2023127380NULL
2024156207380
2024269455620
2024317456945
2024420481745
2024518902048

Si noti che il valore delle vendite del mese precedente è stato riportato nella riga del mese corrente:

Funzione SQL LAG()

Esempi più complessi

Dopo aver appreso come eseguire una semplice query utilizzando la funzione SQL LAG(), vediamo altri modi in cui è possibile utilizzarla nelle analisi.

Uso di LAG() nei calcoli

Spesso si desidera utilizzare i risultati di LAG() nei calcoli. Ad esempio, è possibile visualizzare la differenza e la variazione percentuale tra i mesi. Modifichiamo la query precedente per includere questi calcoli.

È possibile utilizzare i risultati di una funzione nei calcoli come per qualsiasi altra colonna.

La query si presenta così:

SELECT 
  year, 
  month, 
  sales_value, 
  LAG(sales_value) OVER (ORDER BY year, month) AS last_month,
  sales_value - LAG(sales_value) OVER (ORDER BY year, month) AS change,
  ((sales_value - LAG(sales_value) OVER (ORDER BY year, month)) * 100)
   / (LAG(sales_value) OVER (ORDER BY year, month)) AS percentage
FROM monthly_sales;

I risultati sono:

yearmonthsales_valuelast_monthchangepercentage
2023127380NULLNULLNULL
2024156207380-1760-23.85
2024269455620132523.58
2024317456945-5200-74.87
202442048174530317.36
2024518902048-158-7.71

Uso di LAG() con un offset

Negli esempi che abbiamo visto, la query ha preso i dati dalla riga precedente dell'insieme. Questo è il comportamento predefinito. Tuttavia, è possibile andare indietro di più righe specificando un offset.

La sintassi per specificare un offset è la seguente:

LAG(column_1, offset) OVER (ORDER BY column_2)

offset è un numero intero che indica quante righe la query deve cercare all'indietro per trovare i dati. Se non si specifica un offset, il database assume un offset pari a 1.

Supponiamo di voler vedere le vendite di questo mese, quelle del mese scorso e quelle del mese precedente affiancate. La query è:

SELECT 
  year, 
  month, 
  sales_value, 
  LAG(sales_value) OVER (ORDER BY year, month) AS last_month,
  LAG(sales_value,2) OVER (ORDER BY year, month) AS prev_month
FROM monthly_sales;

I risultati sono:

yearmonthsales_valuelast_monthprev_month
2023127380NULLNULL
2024156207380NULL
20242694556207380
20243174569455620
20244204817456945
20245189020481745

Incluso un valore predefinito

Nei risultati che abbiamo visto, la funzione LAG() ha restituito NULL nella prima riga perché non c'era una riga precedente. Non sempre si vuole che lo faccia.

Ad esempio, si supponga che un'azienda abbia aperto nel dicembre 2023. Si potrebbe voler mostrare questo fatto inserendo uno zero nelle vendite dell'ultimo mese di dicembre, in modo che sia evidente che le vendite sono aumentate da zero a 7380 durante quel mese.

Lo zero è chiamato " default", ovvero un valore mostrato quando non esistono cifre.

Per includere un valore predefinito nella query, la sintassi è la seguente:

LAG(column_1, offset, default) OVER (ORDER BY column_2)

Si noti che è sempre necessario specificare un offset se si include un valore predefinito. L'offset sarà 1 se si vuole esaminare la riga immediatamente precedente a quella corrente.

La query per l'esempio precedente è:

SELECT 
  year, 
  month, 
  sales_value, 
  LAG(sales_value, 1, 0) OVER (ORDER BY year, month) AS last_month
FROM monthly_sales;

I risultati sono:

yearmonthsales_valuelast_month
20231273800
2024156207380
2024269455620
2024317456945
2024420481745
2024518902048

Utilizzo di LAG() con PARTITION BY

Supponiamo che i dati originali siano stati ampliati per includere più di un reparto:

departmentyearmonthsales_qtysales_value
Electrical20231210007380
Electrical202418005620
Electrical202429426945
Electrical2024312701745
Electrical2024415202048
Electrical2024514001890
Hardware20231264009000
Hardware2024140006520
Hardware20242700010300
Hardware20243800012000
Hardware20244805014000
Hardware2024560009000

Probabilmente si vorrebbe che ogni reparto fosse tenuto separato nel confronto. Questa operazione è nota come partizionamento. La sintassi per dividere i risultati in partizioni è ...

LAG(column_1) OVER (PARTITION BY column_2 ORDER BY column_3)

... dove column_2 è la colonna che si vuole utilizzare per il partizionamento.

Proviamo a eseguire una query che divida il report per reparto, ma che ordini le righe per anno e mese all'interno di ciascun reparto:

SELECT 
  department, 
  year, 
  month, 
  sales_value, 
  LAG(sales_value) OVER (PARTITION BY department ORDER BY year, month) AS last_month
FROM monthly_sales;

I risultati sono questi:

departmentyearmonthsales_valuelast_month
Electrical2023127380NULL
Electrical2024156207380
Electrical2024269455620
Electrical2024317456945
Electrical2024420481745
Electrical2024518902048
Hardware2023129000NULL
Hardware2024165209000
Hardware20242103006520
Hardware202431200010300
Hardware202441400012000
Hardware20245900014000

Si noti che le vendite del mese scorso tornano a essere NULL sulla prima riga del nuovo reparto.

SQL utilizza department come chiave primaria di ordinamento perché è stata specificata nella clausola PARTITION BY. All'interno di department, mette in sequenza i dati per year e poi per month, come da clausola ORDER BY.

Per ogni riga, cerca se esiste una riga precedente appartenente allo stesso department. In caso affermativo, recupera il contenuto della colonna sales_value dalla riga precedente. Questo viene incluso nella riga corrente come last_month. Se non c'era nessuna riga precedente, last_month viene impostato su un valore NULL.

Utilizzo dei risultati di LAG() per ordinare un report

L'ordine finale del report non deve necessariamente corrispondere alla sequenza utilizzata nella clausola OVER. È possibile utilizzare la normale clausola ORDER BY alla fine della query per specificare una sequenza diversa.

Si supponga di voler visualizzare i risultati in base all'aumento del valore delle vendite tra i mesi.

La query potrebbe avere questo aspetto:

SELECT 
  department, 
  year, 
  month, 
  sales_value, 
  sales_value - LAG(sales_value) OVER (PARTITION BY department ORDER BY year, month) AS change
FROM monthly_sales
ORDER BY
  department, 
  sales_value - LAG(sales_value) OVER (PARTITION BY department ORDER BY year, month);

I risultati appaiono così:

departmentyearmonthsales_valuechange
Electrical2023127380NULL
Electrical202431745-5200
Electrical202415620-1760
Electrical202451890-158
Electrical202442048303
Electrical2024269451325
Hardware2023129000NULL
Hardware202459000-5000
Hardware202416520-2480
Hardware20243120001700
Hardware20244140002000
Hardware20242103003780

Questo può essere utile se si vuole vedere quando l'azienda andava male e quando andava bene. Queste informazioni possono aiutare a risalire all'origine di eventuali problemi.

Dove saperne di più sulla funzione SQL LAG()

Per saperne di più sulla funzione LAG() e sulle funzioni finestra in generale, ecco alcuni articoli che offrono ulteriori informazioni:

Se avete bisogno di ripassare le funzioni della finestra, queste risorse possono esservi utili:

Come ho già detto, se volete davvero diventare esperti, vi consiglio il corso LearnSQL.it'Window Functions (Funzioni Finestra) . Imparerete esattamente come utilizzare tutta la potenza delle funzioni finestra di SQL. Inoltre, potrete acquisire sicurezza risolvendo molti esercizi pratici.

Non c'è niente di meglio della pratica per aumentare le proprie conoscenze e competenze. Se desiderate alcuni esempi guidati su cui lavorare da soli, ecco alcune risorse:

La funzione LAG() di SQL è uno strumento straordinario per analizzare i dati e identificare rapidamente le tendenze e mantenere la competitività dell'azienda. Come analista di dati, vale la pena di dedicare del tempo per diventare un esperto della funzione finestra!