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

Le funzioni a finestra di BigQuery spiegate

Tenersi al passo con le tendenze dell'analisi dei dati dà alla vostra organizzazione - e al vostro CV - un vantaggio. In questo articolo analizzeremo le funzioni finestra di BigQuery e come utilizzarle per ottenere informazioni più approfondite sui dati.

BigQuery di Google, lanciato nel 2010, si sta affermando come una scelta popolare tra le organizzazioni che hanno bisogno di analizzare rapidamente grandi quantità di informazioni e di confrontare i propri dati con quelli statistici di pubblico dominio.

Da quando Google ha allineato il linguaggio di recupero dei dati di BigQuery allo standard SQL e ha incluso caratteristiche avanzate come le funzioni SQL window, la sua popolarità è aumentata. Molte organizzazioni ora includono le competenze in BigQuery come un must, e questo significa che le competenze in SQL sono più richieste che mai. Questo articolo spiega perché la conoscenza di SQL è essenziale per lavorare con BigQuery.

L'SQL continua a essere la competenza principale per chiunque abbia bisogno di lavorare con i dati. Se non siete ancora dei guru dell'SQL, potreste essere interessati al nostro percorso di apprendimentoSQL from A to Z . Si tratta di 7 corsi che vi porteranno dal principiante assoluto all'esperto di SQL. Il corso contiene centinaia di sfide di codifica reali e richiede circa 84 ore per essere completato. Poiché è possibile accedere ai database di esempio attraverso il browser, non è necessario installare alcun software per iniziare.

Cos'è BigQuery?

Google BigQuery è un data warehouse ad alta velocità situato nel cloud. Progettato appositamente per contenere i dati utilizzati per l'analisi, può elaborare petabyte di dati in pochi minuti. Se non vi siete ancora abituati ai petabyte, un petabyte è un quadrilione di byte (o un milione di gigabyte).

In BigQuery si paga per quello che si usa, quindi il costo dell'archiviazione e dell'analisi di enormi quantità di dati è di solito molto più basso rispetto all'investimento in molti dischi rigidi. Inoltre, poiché tutti i tipi di dati statistici utili provenienti da governi e organizzazioni mondiali sono archiviati pubblicamente in BigQuery, è possibile accedervi per capire come migliorare le prestazioni della propria organizzazione.

Cosa sono le funzioni SQL Window Functions?

Le funzioni a finestra sono note anche come funzioni analitiche o funzioni OVER. Sono state aggiunte allo standard SQL nel 2003 e la maggior parte dei principali fornitori di database ha iniziato a implementarle a partire dal 2010. Si tratta quindi di un'aggiunta abbastanza recente a SQL.

Prima che le funzioni finestra fossero incluse in SQL, era possibile elencare singole righe o calcolare aggregati come totali e medie. Non era possibile fare entrambe le cose nella stessa query, a meno che non si scrivessero sottoquery complesse e probabilmente lente e inefficienti.

Ciò significa che si può avere un elenco come questo ...

Student IDSubjectScore
1Math63
1Science50
2Math59

... o mostrare aggregati come questo:

SubjectClass Average
Math52
Science61
English55
Overall Average56

In questo esempio, se si volesse sapere come il punteggio di un singolo studente si confronta con la media della classe, bisognerebbe guardare i due report uno accanto all'altro. Sarebbe molto più bello se si potesse vedere la media della classe sulla stessa riga del punteggio di uno studente, come in questo caso:

Student IDSubjectScoreClass Average
1Math6362
1Science5061
2Math5952

Come ho già detto, si potrebbe ottenere questo risultato usando le subquery. Ma le subquery sono notoriamente lente da eseguire e possono rendere la query molto complicata.

Questo è il genere di cose che le funzioni finestra consentono di fare in modo semplice ed efficiente: includere gli aggregati insieme ai dettagli sulla stessa riga.

Perché si chiamano Window Functions?

Si chiamano funzioni finestra perché, mentre si osserva una singola riga, si può anche "guardare attraverso la finestra" ed estrarre informazioni dall'intero set di dati o dalle righe correlate alla riga corrente.

A titolo di esempio, consideriamo una tabella di voti degli studenti:

Student IDTeacher IDSubjectGrade
11Math63
21Math80
32Math60
42Math45
51Math52
61Math70
72Math65
12Science70
22Science62
32Science90
42Science30
52Science53
15English59
35English70
55English45
65English62
112History55
312History67
412History58

Come nell'esempio precedente, vogliamo mostrare la media della classe accanto a ogni studente, in modo che una singola riga abbia questo aspetto:

Student IDSubjectGradeClass Average
4Math4562

Per fare ciò, dobbiamo considerare la media di tutti gli altri studenti quando estraiamo questa riga e mostrare il risultato accanto agli altri dati.

Spiegazione delle funzioni della finestra di BigQuery

In SQL, le funzioni finestra utilizzano una finestra scorrevole di righe per estrarre informazioni aggiuntive dall'intero set di dati o da un sottoinsieme relativo alla riga corrente.

Nella figura precedente, la riga corrente è un risultato matematico e la finestra include tutti i voti matematici.

Per estrarre questa riga ...

Student IDSubjectGradeClass Average
1Science7062

... avremo bisogno che la finestra "scorra" in modo da visualizzare tutti i risultati di scienze per calcolare la media di scienze.

Le funzioni finestra hanno molte delle stesse capacità della clausola GROUP BY, ma la differenza è che consentono di visualizzare aggregati e dettagli fianco a fianco.

Sintassi di BigQuery Window Functions

La clausola OVER()

La clausola OVER() indica che si sta utilizzando una funzione finestra. Si scrive la query come di consueto e si includono gli aggregati desiderati accanto ai nomi delle altre colonne. Ogni aggregato è identificato con la clausola OVER(). Quando si usa questa clausola da sola, la "finestra" è l'intero set di dati. Le finestre scorrevoli saranno trattate più avanti nell'articolo.

Per esempio, se si volessero estrarre tutti i risultati di matematica e mostrare la media della classe e il voto più alto e più basso rispetto al voto di ogni studente, la query avrebbe questo aspetto:

SELECT 
  student_id,
  grade,
  AVG(grade) OVER() AS average,
  MIN(grade) OVER() AS lowest,
  MAX(grade) OVER() AS highest
FROM exam_results
WHERE subject = 'Math';

I risultati sarebbero quindi così:

student_idgradeaveragelowesthighest
163624580
280624580
360624580
445624580
552624580
670624580
765624580

La clausola PARTITION BY

Questa clausola utilizza una finestra scorrevole. Invece di una finestra contenente l'intero set di dati, include solo una partizione (o una parte) del set.

Nell'esempio precedente, ho incluso solo i risultati matematici escludendo tutti gli altri utilizzando la clausola WHERE. Se si desidera un report che mostri i risultati di tutti i soggetti, ma che calcoli la media utilizzando solo le righe in cui il soggetto corrisponde alla riga corrente, si deve utilizzare la clausola PARTITION BY:

SELECT 
  student_id,
  subject,
  grade,
  AVG(grade) OVER(PARTITION BY subject) AS average
FROM exam_results;

Guardate questa copia codificata a colori della tabella dei voti degli studenti per vedere come funzionano le partizioni:

Student IDTeacher IDSubjectGrade
11Math63
21Math80
32Math60
42Math45
51Math52
61Math70
72Math65
12Science70
22Science62
32Science90
42Science30
52Science53
15English59
35English70
55English45
65English62
112History55
312History67
412History58

Quando si elabora ogni riga, le righe incluse nella finestra cambiano in base al valore della colonna subject. Ciò significa che la media viene calcolata solo per la partizione del set di dati in cui il soggetto corrisponde alla riga corrente. È possibile visualizzarlo in questo modo:

Spiegazione delle funzioni della finestra di BigQuery

I risultati appaiono così:

Student IDSubjectGradeClass Average
1Math6362
2Math8062
3Math6062
4Math4562
5Math5262
6Math7062
7Math6562
1Science7061
2Science6261
3Science9061
4Science3061
5Science5361
1English5959
3English7059
5English4559
6English6259
1History5560
3History6760
4History5860

La clausola ORDER BY

La clausola ORDER BY all'interno della funzione OVER() utilizza un tipo diverso di finestra scorrevole. Quando si utilizza OVER(ORDER BY column_name), la finestra include solo le righe in cui il valore della colonna specificata è inferiore o uguale al valore della colonna nella riga corrente.

La clausola ORDER BY è utile per calcolare i totali progressivi e le medie mobili. Come esempio, utilizzeremo una tabella chiamata monthly_transactions che contiene le transazioni dei conti bancari:

account_idtran_datetransactionvalue
12023-09-01Opening Balance500.00
12023-09-03Deposit137.45
12023-09-12Withdrawal-200.00
12023-09-18Withdrawal-250.00
22023-09-01Opening Balance1200.00
22023-09-14Deposit900.00
22023-09-20Purchase-318.90

La query seguente elenca le transazioni per l'ID conto 1, mostrando il saldo corrente.

SELECT 
  account_id,
  tran_date,
  transaction,
  value,
  SUM(value) OVER(ORDER BY tran_date) AS balance
FROM monthly_transactions
WHERE account_id = 1;

L'inclusione della clausola ORDER BY all'interno della clausola OVER controlla una finestra scorrevole.

Se si vuole, si può anche usare la clausola ORDER BY alla fine della query per controllare l'ordine finale delle righe nel report. Non è necessario che vengano mostrate nell'ordine originale.

Per impostazione predefinita, l'uso di ORDER BY all'interno della clausola OVER fa sì che la finestra scorra in modo da visualizzare solo le righe la cui data è inferiore o uguale a quella della riga corrente. Esistono altre parole chiave che possono modificare questa impostazione predefinita, ma sono un po' al di là dello scopo di questo articolo.

È possibile visualizzarlo in questo modo:

Spiegazione delle funzioni della finestra di BigQuery

I risultati sarebbero i seguenti:

account_idtran_datetransactionvaluebalance
12023-09-01Opening Balance500.00500.00
12023-09-03Deposit137.45637.45
12023-09-12Withdrawal-200.00437.45
12023-09-18Withdrawal-250.00187.45
22023-09-01Opening Balance1200.001200.00
22023-09-14Deposit900.002100.00
22023-09-20Purchase-318.901781.10

Uso di ORDER BY con la clausola PARTITION BY

Se si desidera mostrare tutti i conti con i relativi saldi correnti, è possibile utilizzare insieme le clausole PARTITION BY e ORDER BY:

SELECT 
  account_id,
  tran_date,
  transaction,
  value,
  SUM(value) OVER(PARTITION BY account_id ORDER BY tran_date) AS balance
FROM monthly_transactions
ORDER BY account_id, tran_date

La clausola PARTITION BY farà sì che la finestra scorrevole includa solo le righe in cui account_id corrisponde alla riga corrente. La clausola ORDER BY fa sì che vengano incluse solo le righe all'interno della partizione in cui la data è inferiore o uguale alla data della riga corrente.

I risultati sarebbero:

account_idtran_datetransactionvaluebalance
12023-09-01Opening Balance500.00500.00
12023-09-03Deposit137.45637.45
12023-09-12Withdrawal-200.00437.45
12023-09-18Withdrawal-250.00187.45
22023-09-01Opening Balance1200.001200.00
22023-09-14Deposit900.002100.00
22023-09-20Purchase-318.901781.10

Ogni conto ha il proprio saldo corrente separato.

SQL Window Functions Disponibile in BigQuery

Abbiamo visto come le comuni funzioni aggregate SQL, come SUM(), AVG(), MIN() e MAX(), possano essere utilizzate insieme alla clausola OVER per estrarre aggregati da una finestra di dati.

Google BigQuery, come molti altri dialetti SQL, dispone di funzioni aggiuntive che possono fornire informazioni più approfondite sui dati. Ecco alcuni esempi.

RANK()

Questa funzione classifica il set di dati dal più alto al più basso su una colonna specificata. Può rispondere a domande come:

  • Qual è il posto di ogni studente nella classe, in base ai risultati degli esami?
  • Quali prodotti sono stati più redditizi?
  • Quali clienti hanno speso di più?
  • Quale magazzino ha ricevuto più reclami?

Utilizzando la tabella di esempio vista in precedenza, classifichiamo gli studenti in base ai risultati degli esami utilizzando questa query:

SELECT 
  student_id,
  subject,
  grade,
  RANK() OVER(PARTITION BY subject ORDER BY grade desc) AS place
FROM exam_results
ORDER BY subject, grade DESC;

Il risultato sarebbe:

student_idsubjectgradeplace
3English701
6English622
1English593
5English454
3History671
4History582
1History553
2Math801
6Math702
7Math653
1Math634
3Math605
5Math526
4Math457
3Science901
1Science702
2Science623
5Science534
4Science305

Nel calcolare questi risultati, la clausola PARTITION BY subject fa sì che SQL esamini solo i risultati relativi alla stessa materia della riga corrente. La clausola ORDER BY grade DESC li ordina in ordine decrescente di voto. La funzione RANK() classifica quindi gli studenti in quest'ordine.

Poiché lo studente 3 ha il voto più alto in Inglese, la sua posizione è 1; lo studente 6, il più alto, è al secondo posto in questa materia. Lo studente 2 ha il voto più alto in Matematica e viene classificato come 1.

DENSE_RANK()

DENSE_RANK() è utilizzato per lo stesso scopo di RANK. La differenza tra i due metodi può essere spiegata meglio osservando i risultati di queste query, che rappresentano i punteggi di una gara di tiro.

Utilizzando RANK, la query sarebbe:

SELECT 
  competitor_no,
  score,
  RANK() OVER(ORDER BY score desc) AS rank
FROM match_results
ORDER BY score DESC;

I risultati sono:

Competitor NoScoreRank
4851
5832
10832
9814
2765
6765
7727
3708
8689
16210

I concorrenti 5 e 10 hanno pareggiato per il secondo posto e hanno ricevuto entrambi un punteggio di 2. Il concorrente 9 è il prossimo più alto e si classifica a 4. Il terzo posto è stato escluso.

Utilizzando DENSE_RANK, la query è:

SELECT 
  competitor_no,
  score,
  DENSE RANK() OVER(ORDER BY score desc) AS rank
FROM match_results
ORDER BY score DESC;

I risultati sono:

Competitor NoScoreRank
4851
5832
10832
9813
2764
6764
7725
3706
8687
1628

I concorrenti 5 e 10 sono ancora entrambi classificati come 2, ma il terzo posto non viene escluso: Il concorrente 9 ha ora una posizione in classifica pari a 3.

Entrambe le funzioni hanno la stessa sintassi. Se volessimo ricodificare la query dei voti degli studenti precedenti usando la funzione DENSE_RANK(), il risultato sarebbe questo:

SELECT 
  student_id,
  subject,
  grade,
  DENSE_RANK() OVER(PARTITION BY subject ORDER BY grade desc) AS class_place
FROM exam_results
ORDER BY subject, grade DESC

Ma poiché non ci sono valori di parità, il risultato sarebbe lo stesso.

NUMERO_RIGHE()

La funzione ROW_NUMBER() funziona in modo simile alle due funzioni precedenti, ma le righe sono semplicemente numerate in ordine. Se le righe hanno lo stesso valore, saranno numerate consecutivamente, a seconda di quale sia stata incontrata per prima. Ecco i risultati dell'interrogazione sulla gara di tiro utilizzando ROW_NUMBER() invece di RANK() o DENSE_RANK():

Competitor NoScoreRank
4851
5832
10833
9814
2765
6766
7727
3708
8689
16210

LAG()

Questa funzione consente di confrontare i dati della riga precedente del set di risultati con quelli della riga corrente. È ideale per i confronti anno per anno, per scoprire le tendenze e identificare i problemi di performance aziendale.

LAG() e la funzione correlata LEAD() può essere utilizzata solo in combinazione con la clausola OVER(ORDER BY).

A titolo di esempio, si consideri la tabella seguente, che contiene i dati di vendita di una piccola azienda:

yearsales_valuesales_quantityprofit
2019540009008000
202075000120011000
2021300004501000
202260000100007000

La query di esempio per confrontare i dati anno per anno è la seguente:

SELECT 
  year,
  sales_value,
  sales_quantity,
  profit,
  LAG(sales_value) OVER(ORDER BY year) as ly_value,
  LAG(sales_quantity) OVER(ORDER BY year) as ly_qty,
  LAG(profit) OVER(ORDER BY year) as ly_profit,
  profit - LAG(profit) OVER(ORDER BY year) as inc_dec
FROM annual_sales
ORDER BY year;

I risultati di questa query sono:

yearsales_valuesales_quantityprofitly_valuely_qtyly_profitinc_dec
2019540009008000NULLNULLNULLNULL
2020750001200110005400090080003000
202130000450100075000120011000-10000
2022600001000070003000045010006000

Esaminiamo questa riga della query per vedere cosa ha effettivamente fatto:

LAG(sales_value) OVER(ORDER BY year) as ly_value

Su questa riga del risultato ...

yearsales_valuesales_quantityprofitly_valuely_qtyly_profitinc_dec
2020750001200110005400090080003000

... la nostra riga attuale si riferisce all'anno 2020. La funzione LAG() insieme a ORDER BY year fa sì che SQL esamini la riga dell'anno precedente (2019) e ne estragga il valore delle vendite sotto la voce ly_value.

Si noterà che nella prima riga le colonne calcolate dalla funzione LAG() contengono un valore nullo, poiché non esiste un record precedente.

LEAD()

La funzione LEAD() è l'inverso di LAG(): ottiene i dati dalla riga successiva a quella corrente, anziché da quella precedente.

Per confrontare i profitti tra l'anno in corso, l'anno precedente e l'anno successivo utilizzando la stessa tabella di esempio, la query sarebbe:

SELECT 
  year,
  profit,
  LAG(profit) OVER(ORDER BY year) as ly_profit,
  profit - LAG(profit) OVER(ORDER BY year) as ly_inc_dec,
  LEAD(profit) OVER(ORDER BY year) as ny_profit,
  LEAD(profit) OVER(ORDER BY year) - profit as ny_inc_dec
FROM annual_sales
ORDER BY year;

I risultati di questa query sarebbero:

yearprofitly_profitly_inc_decny_profitny_inc_dec
20198000NULLNULL110003000
202011000800030001000-10000
2021100011000-1000070006000
2022700010006000NULLNULL

Le colonne ny_profit e ny_inc_dec utilizzano la funzione LEAD(), che fa sì che SQL guardi alla riga successiva in sequenza per estrarre questi campi. Se la riga corrente è quella del 2019, questi due campi verranno estratti dalla riga del 2020.

Questo dovrebbe avervi dato un'idea di alcune delle utili funzioni SQL a finestra disponibili in BigQuery. L'elenco completo delle funzioni è disponibile nella documentazione di BigQuery SQL.

Per ulteriori esempi di funzioni finestra, consultare l'articolo Esempi di funzioni finestra SQL. È inoltre possibile trovare una guida rapida alla sintassi delle funzioni finestra SQL nel nostro Window Functions Cheat Sheet.

Usi pratici di BigQuery Window Functions

Nel mondo reale, le funzioni finestra di BigQuery possono fornire informazioni utili per migliorare le prestazioni dell'organizzazione. Sono molto potenti e consentono di produrre rapidamente report complessi.

Ecco alcune idee su come possono essere utilizzate le funzioni finestra di BigQuery:

I prossimi passi con BigQuery Window Functions

Ora che avete visto cosa possono fare le funzioni della finestra SQL in BigQuery e in altri sistemi di gestione di database, è il momento di pensare a migliorare le vostre competenze in questo importante settore.

Un buon punto di partenza è il corso SQL Window Functions di LearnSQL.it. Imparerete passo dopo passo come utilizzare le tecniche che avete visto in questo articolo, con una spiegazione completa di ogni argomento. Potrete anche fare molta pratica, con oltre 200 esercizi interattivi per assicurarvi di sapere come estrarre informazioni complesse in situazioni reali. L'aiuto è disponibile quando ci si blocca e si potrà accedere a database di esempio attraverso il browser. Il corso richiede circa 20 ore per essere completato.

Se volete davvero diventare degli esperti, potete fare più pratica nella risoluzione di problemi complessi lavorando con il nostro set di esercitazioni Window Functions. Affronterete 100 esempi di report complessi utilizzando tre diversi database.

Potete anche leggere questo articolo su come esercitarsi con le funzioni delle finestre e trovare maggiori informazioni sulla sintassi di BigQuery qui.

Se siete alla ricerca di un lavoro di alto livello nel campo dell'analisi dei dati o della scienza dei dati, è molto probabile che durante il colloquio vi venga chiesto di dimostrare la vostra conoscenza delle funzioni SQL a finestra. Per avere un'idea del tipo di domande che potrebbero esservi poste (e di come rispondere), ecco un articolo che illustra le principali domande di colloquio sulle funzioni SQL a finestra.

Fate i primi passi oggi stesso per portare le vostre capacità di analisi dei dati al livello successivo!