Prova questo notebook in Databricks
Dai un'occhiata all'ebook Perché il data lakehouse è il tuo prossimo data warehouse per scoprire i meccanismi interni della Databricks Lakehouse Platform.
AGGIORNATO AL 10/11/2018
Pivot è stato introdotto per la prima volta in Apache Spark 1.6 come nuova funzionalità DataFrame che consente agli utenti di ruotare un'espressione con valori di tabella trasformando i valori univoci di una colonna in singole colonne.
La versione Apache Spark 2.4 estende questa potente funzionalità di pivoting dei dati anche ai nostri utenti SQL. In questo blog, utilizzando le registrazioni delle temperature a Seattle, mostreremo come possiamo utilizzare questa comune funzionalità SQL Pivot per ottenere trasformazioni complesse dei dati.
Quest'estate a Seattle le temperature sono salite a livelli insopportabili, raggiungendo picchi elevati tra gli 80 e i 90 gradi, per nove giorni a luglio.
| Data | Temperatura (°F) |
|---|---|
| 07-22-2018 | 86 |
| 07-23-2018 | 90 |
| 07-24-2018 | 91 |
| 07-25-2018 | 92 |
| 07-26-2018 | 92 |
| 07-27-2018 | 88 |
| 07-28-2018 | 85 |
| 07-29-2018 | 94 |
| 07-30-2018 | 89 |
Supponiamo di voler esplorare o esaminare se ci fosse una tendenza storica all'aumento dei livelli di mercurio. Un modo intuitivo per esaminare e presentare questi numeri è avere i mesi come colonne e quindi le medie mensili massime di ogni anno in una singola riga. In questo modo sarà facile confrontare le temperature sia orizzontalmente, tra mesi adiacenti, sia verticalmente, tra anni diversi.
Ora che abbiamo il supporto per la sintassi PIVOT in Spark SQL, possiamo ottenerlo con la seguente query SQL.
La query precedente produrrà un risultato simile a:
| ANNO | GEN | FEB | MAR | APR | MAG | GIU | LUG | AGO | SET | OTT | NOV | DIC |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2018 | 49.7 | 45.8 | 54.0 | 58.6 | 70.8 | 71.9 | 82.8 | 79.1 | NULL | NULL | NULL | NULL |
| 2017 | 43.7 | 46.6 | 51.6 | 57.3 | 67.0 | 72.1 | 78.3 | 81.5 | 73.8 | 61.1 | 51.3 | 45.6 |
| 2016 | 49.1 | 53.6 | 56.4 | 65.9 | 68.8 | 73.1 | 76.0 | 79.5 | 69.6 | 60.6 | 56.0 | 41.9 |
| 2015 | 50.3 | 54.5 | 57.9 | 59.9 | 68.0 | 78.9 | 82.6 | 79.0 | 68.5 | 63.6 | 49.4 | 47.1 |
Beh, sembra che ci siano anni buoni e anni cattivi. L'anno 2016 sembra un anno piuttosto favorevole all'energia.
Diamo un'occhiata più da vicino a questa query per capire come funziona. Innanzitutto, dobbiamo specificare la clausola FROM, che è l'input del pivot, in altre parole, la tabella o la sottoquery in base alla quale verrà eseguito il pivoting. Nel nostro caso, siamo interessati agli anni, ai mesi e alle temperature elevate, quindi questi sono i campi che compaiono nella sottoquery.
In secondo luogo, consideriamo un'altra parte importante della query, la clausola PIVOT. Il primo argomento della clausola PIVOT è una funzione di aggregazione e la colonna da aggregare. Quindi specifichiamo la colonna pivot nella sotto-clausola FOR come secondo argomento, seguito dall'operatore IN contenente i valori della colonna pivot come ultimo argomento.
La colonna pivot è il punto attorno al quale verrà ruotata la tabella e i valori della colonna pivot verranno trasposti in colonne nella tabella di output. La clausola IN consente inoltre di specificare un alias per ogni valore pivot, semplificando la generazione di nomi di colonna più significativi.
Un'idea importante sul pivot è che esegue un'aggregazione raggruppata in base a un elenco di colonne group-by implicite insieme alla colonna pivot. Le colonne group-by implicite sono colonne della clausola FROM che non compaiono in alcuna funzione di aggregazione o come colonna pivot.
Nella query precedente, con la colonna pivot che è la colonna month e la colonna group-by implicita che è la colonna year, l'espressione avg(temp) verrà aggregata su ogni coppia di valori distinti di (year, month), dove month è uguale a uno dei valori della colonna pivot specificati. Di conseguenza, ciascuno di questi valori aggregati verrà mappato nella cella corrispondente della riga year e del mese column.
Vale la pena notare che a causa di questo group-by implicito, dobbiamo assicurarci che qualsiasi colonna che non desideriamo faccia parte dell'output pivot venga esclusa dalla clausola FROM, altrimenti la query produrrebbe risultati indesiderati.
L'esempio precedente mostra solo un'espressione di aggregazione utilizzata nella clausola PIVOT, mentre in realtà, gli utenti possono specificare più espressioni di aggregazione, se necessario. Ancora una volta, con i dati meteorologici di cui sopra, possiamo elencare le temperature massime elevate insieme alle temperature medie elevate tra giugno e settembre.
In caso di più espressioni di aggregazione, le colonne saranno il prodotto cartesiano dei valori della colonna pivot e delle espressioni di aggregazione, con i nomi come .
| anno | GIU_media | GIU_max | LUG_media | LUG_max | AGO_media | AGO_max | SET_media | SET_max |
|---|---|---|---|---|---|---|---|---|
| 2018 | 71.9 | 88 | 82.8 | 94 | 79.1 | 94 | NULL | NULL |
| 2017 | 72.1 | 96 | 78.3 | 87 | 81.5 | 94 | 73.8 | 90 |
| 2016 | 73.1 | 93 | 76.0 | 89 | 79.5 | 95 | 69.6 | 78 |
| 2015 | 78.9 | 92 | 82.6 | 95 | 79.0 | 92 | 68.5 | 81 |
Ora supponiamo di voler includere le basse temperature nella nostra esplorazione delle tendenze della temperatura da questa tabella delle temperature giornaliere basse:
| Data | Temperatura (°F) |
|---|---|
| ... | ... |
| 08-01-2018 | 59 |
| 08-02-2018 | 58 |
| 08-03-2018 | 59 |
| 08-04-2018 | 58 |
| 08-05-2018 | 59 |
| 08-06-2018 | 59 |
| ... | ... |
Per combinare questa tabella con la precedente tabella delle temperature giornaliere elevate, potremmo unire queste due tabelle nella colonna "Data". Tuttavia, poiché useremo pivot, che esegue il raggruppamento per date, possiamo semplicemente concatenare le due tabelle usando UNION ALL. E vedrai più avanti, questo approccio ci offre anche maggiore flessibilità:
Ora proviamo la nostra query pivot con la nuova tabella combinata:
Di conseguenza, otteniamo la media alta e la media bassa per ogni mese degli ultimi 4 anni in una tabella. Tieni presente che dobbiamo includere la colonna flag nella query pivot, altrimenti l'espressione avg(temp) si baserebbe su un mix di temperature alte e basse.
| anno | H/L | GIU | LUG | AGO | SET |
|---|---|---|---|---|---|
| 2018 | H | 71.9 | 82.8 | 79.1 | NULL |
| 2018 | L | 53.4 | 58.5 | 58.5 | NULL |
| 2017 | H | 72.1 | 78.3 | 81.5 | 73.8 |
| 2017 | L | 53.7 | 56.3 | 59.0 | 55.6 |
| 2016 | H | 73.1 | 76.0 | 79.5 | 69.9 |
| 2016 | L | 53.9 | 57.6 | 59.9 | 52.9 |
| 2015 | H | 78.9 | 82.6 | 79.0 | 68.5 |
| 2015 | L | 56.4 | 59.9 | 58.5 | 52.5 |
Potresti aver notato che ora abbiamo due righe per ogni anno, una per le temperature elevate e l'altra per le temperature basse. Questo perché abbiamo incluso un'altra colonna, flag, nell'input pivot, che a sua volta diventa un'altra colonna di raggruppamento implicita oltre alla colonna originale year.
In alternativa, invece di essere una colonna di raggruppamento, il flag può anche fungere da colonna pivot. Quindi ora abbiamo due colonne pivot, month e flag:
Questa query ci presenta un layout diverso degli stessi dati, con una riga per ogni anno, ma due colonne per ogni mese.
| anno | GIU_hi | GIU_lo | LUG_hi | LUG_lo | AGO_hi | AGO_lo | SET_hi | SET_lo |
|---|---|---|---|---|---|---|---|---|
| 2018 | 71.9 | 53.4 | 82.8 | 58.5 | 79.1 | 58.5 | NULL | NULL |
| 2017 | 72.1 | 53.7 | 78.3 | 56.3 | 81.5 | 59.0 | 73.8 | 55.6 |
| 2016 | 73.1 | 53.9 | 76.0 | 57.6 | 79.5 | 57.9 | 69.6 | 52.9 |
| 2015 | 78.9 | 56.4 | 82.6 | 59.9 | 79.0 | 58.5 | 68.5 | 52.5 |
Per eseguire gli esempi di query utilizzati in questo blog, consulta gli esempi SQL pivot in questo notebook di accompagnamento.
Grazie ai collaboratori della community di Apache Spark per i loro contributi!
(Questo post sul blog è stato tradotto utilizzando strumenti basati sull'intelligenza artificiale) Post originale
