Probieren Sie dieses Notebook in Databricks aus
Sehen Sie sich das E-Book Warum das Data Lakehouse Ihr nächstes Data Warehouse ist an, um die Funktionsweise der Databricks Lakehouse Platform kennenzulernen.
AKTUALISIERT AM 10.11.2018
Pivot wurde erstmals in Apache Spark 1.6 als neue DataFrame-Funktion eingeführt, die es Benutzern ermöglicht, einen Tabellenausdruck zu drehen, indem die eindeutigen Werte aus einer Spalte in einzelne Spalten umgewandelt werden.
Die Version Apache Spark 2.4 erweitert diese leistungsstarke Funktionalität der Datendrehung auch auf unsere SQL-Benutzer. In diesem Blog zeigen wir anhand von Temperaturaufzeichnungen in Seattle, wie wir diese gängige SQL-Pivot-Funktion verwenden können, um komplexe Datentransformationen zu erzielen.
In diesem Sommer stiegen die Temperaturen in Seattle auf unangenehme Werte und erreichten an neun Tagen im Juli Höchstwerte von über 26 bis 32 Grad Celsius.
| Datum | Temperatur (°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 |
Angenommen, wir möchten untersuchen, ob es einen historischen Trend bei steigenden Quecksilberwerten gab. Eine intuitive Möglichkeit, diese Zahlen zu untersuchen und darzustellen, besteht darin, die Monate als Spalten und dann die monatlichen Durchschnittswerte jedes Jahres in einer einzigen Zeile darzustellen. Auf diese Weise ist es einfach, die Temperaturen sowohl horizontal, zwischen benachbarten Monaten, als auch vertikal, zwischen verschiedenen Jahren, zu vergleichen.
Nachdem wir nun die PIVOT-Syntax in Spark SQL unterstützen, können wir dies mit der folgenden SQL-Abfrage erreichen.
Die obige Abfrage erzeugt ein Ergebnis wie folgt:
| JAHR | JAN | FEB | MÄR | APR | MAI | JUNI | JULI | AUG | SEPT | OKT | NOV | DEZ |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 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 |
Nun, es sieht so aus, als gäbe es gute und schlechte Jahre. Das Jahr 2016 scheint ein eher energiesparendes Jahr zu sein.
Werfen wir einen genaueren Blick auf diese Abfrage, um zu verstehen, wie sie funktioniert. Zuerst müssen wir die FROM-Klausel angeben, die die Eingabe des Pivots ist, mit anderen Worten, die Tabelle oder Unterabfrage, auf der die Pivotierung durchgeführt wird. In unserem Fall interessieren wir uns für die Jahre, die Monate und die hohen Temperaturen, also sind dies die Felder, die in der Unterabfrage erscheinen.
Zweitens betrachten wir einen weiteren wichtigen Teil der Abfrage, die PIVOT-Klausel. Das erste Argument der PIVOT-Klausel ist eine Aggregatfunktion und die zu aggregierende Spalte. Anschließend geben wir die Pivotspalte in der FOR-Unterklausel als zweites Argument an, gefolgt vom Operator IN, der die Pivotspaltenwerte als letztes Argument enthält.
Die Pivotspalte ist der Punkt, um den die Tabelle gedreht wird, und die Pivotspaltenwerte werden in Spalten in der Ausgabetabelle transponiert. Mit der IN-Klausel können Sie auch einen Alias für jeden Pivotwert angeben, wodurch es einfach ist, aussagekräftigere Spaltennamen zu generieren.
Eine wichtige Idee bei Pivot ist, dass es eine gruppierte Aggregation basierend auf einer Liste von impliziten group-by-Spalten zusammen mit der Pivotspalte durchführt. Die impliziten group-by-Spalten sind Spalten aus der FROM-Klausel, die in keiner Aggregatfunktion oder als Pivotspalte vorkommen.
In der obigen Abfrage, wobei die Pivotspalte die Spalte month und die implizite group-by-Spalte die Spalte year ist, wird der Ausdruck avg(temp) für jedes eindeutige Wertepaar von (year, month) aggregiert, wobei month einem der angegebenen Pivotspaltenwerte entspricht. Infolgedessen wird jeder dieser aggregierten Werte seiner entsprechenden Zelle der Zeile year und der column month zugeordnet.
Es ist erwähnenswert, dass wir aufgrund dieser impliziten group-by sicherstellen müssen, dass jede Spalte, die nicht Teil der Pivot-Ausgabe sein soll, aus der FROM-Klausel entfernt wird, da die Abfrage sonst unerwünschte Ergebnisse liefern würde.
Das obige Beispiel zeigt nur einen Aggregatausdruck, der in der PIVOT-Klausel verwendet wird, während Benutzer bei Bedarf tatsächlich mehrere Aggregatausdrücke angeben können. Auch hier können wir mit den obigen Wetterdaten die maximalen Höchsttemperaturen zusammen mit den durchschnittlichen Höchsttemperaturen zwischen Juni und September auflisten.
Im Fall von mehreren Aggregatausdrücken sind die Spalten das kartesische Produkt der Pivotspaltenwerte und der Aggregatausdrücke, wobei die Namen lauten.
| year | JUN_avg | JUN_max | JUL_avg | JUL_max | AUG_avg | AUG_max | SEP_avg | SEP_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 |
Nehmen wir nun an, wir möchten die niedrigen Temperaturen in unsere Untersuchung der Temperaturtrends aus dieser Tabelle der täglichen niedrigen Temperaturen einbeziehen:
| Datum | Temperatur (°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 |
| ... | ... |
Um diese Tabelle mit der vorherigen Tabelle der täglichen Höchsttemperaturen zu kombinieren, könnten wir diese beiden Tabellen über die Spalte „Datum“ verknüpfen. Da wir jedoch Pivot verwenden werden, das eine Gruppierung nach Datum durchführt, können wir die beiden Tabellen einfach mit UNION ALL verketten. Und Sie werden später sehen, dass dieser Ansatz uns auch mehr Flexibilität bietet:
Versuchen wir nun unsere Pivot-Abfrage mit der neuen kombinierten Tabelle:
Als Ergebnis erhalten wir die durchschnittlichen Höchst- und Tiefstwerte für jeden Monat der letzten 4 Jahre in einer Tabelle. Beachten Sie, dass wir die Spalte flag in die Pivot-Abfrage aufnehmen müssen, da der Ausdruck avg(temp) sonst auf einer Mischung aus hohen und niedrigen Temperaturen basieren würde.
| year | H/L | JUN | JUL | AUG | SEP |
|---|---|---|---|---|---|
| 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 |
Sie haben vielleicht bemerkt, dass wir jetzt zwei Zeilen für jedes Jahr haben, eine für die hohen Temperaturen und die andere für die niedrigen Temperaturen. Das liegt daran, dass wir eine weitere Spalte, flag, in die Pivot-Eingabe aufgenommen haben, die wiederum zu einer weiteren impliziten Gruppierungsspalte zusätzlich zur ursprünglichen Spalte year wird.
Alternativ kann die flag, anstatt eine Gruppierungsspalte zu sein, auch als Pivotspalte dienen. Wir haben also jetzt zwei Pivotspalten, month und flag:
Diese Abfrage präsentiert uns ein anderes Layout derselben Daten, mit einer Zeile für jedes Jahr, aber zwei Spalten für jeden Monat.
| year | JUN_hi | JUN_lo | JUL_hi | JUL_lo | AUG_hi | AUG_lo | SEP_hi | SEP_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 |
Um die in diesem Blog verwendeten Abfragebeispiele auszuführen, überprüfen Sie bitte die Pivot-SQL-Beispiele in diesem begleitenden Notebook.
Vielen Dank an die Mitwirkenden der Apache Spark-Community für ihre Beiträge!
(Dieser Blogbeitrag wurde mit KI-gestützten Tools übersetzt.) Originalbeitrag
