DAX - Grundoperation CrossJoin

Von Lukas Hillesheim, 8. September 2022
Blog Article & Copyright by Lukas Hillesheim
Der erste Artikel dieser Serie soll die komplexe Sprache DAX aus der Sicht anderer Konzepte beleuchten, im Internet wird dafür gerne der Begriff Projektion verwendet. Mit den anderen Konzepten sind Mengen-Konzepte, OOP-Konzepte und SQL gemeint. Konzepte aus anderen Sprachen sollen dabei helfen, die relativ schwer zu erlernende Sprache DAX transparenter zu machen und die grundlegenden DAX-Objekte und DAX-Verhaltensweisen wie Tabelle, Spalte, Relationship etc. aus deren Sicht zu erklären.

1. DAX als Sprache für Endanwender

SelfService. Bei der Entwicklung von DAX wie auch des Tabularen Modells innerhalb von Power BI und des Tabularen Modells innerhalb von Analysis Services Tabular steht der Gedanke von SelfService im Vordergrund. Daher ist die Usability der BI Produkte auf PowerUser, nicht auf BI Professionals getrimmt. Komplexität wird vor dem DAX-Entwickler möglichst verborgen und viele Standard-Verhaltensweisen der Sprache DAX und des Produkts Power BI sorgen für kompakten Code und einen schnellen Weg zum Ziel.
Komplexität. Dass DAX eine wirklich komplexe Sprache ist, zeigt sich für den beginnenden DAX-Entwickler daher zunächst nicht. Die Tatsache der Komplexität und deren Gründe war daher einen eigenen Artikel wert.
Meine Serie soll dabei helfen, die Verhaltensweisen der Sprache zu verstehen. Dabei greife ich auf verschiedene andere Konzepte zurück:
  • - Mengen-Konzepte. Objekte wie Sets, Tupels, Member
  • - Operationen wie CROSSJOIN, INTERSECT, EXCEPT
  • - SQL-Code
  • - OOP-Pseudo-Code
Mengen-Konzepte und Tupels. Wenn man sich vor Augen hält, dass MDX und DAX als Geschwister-Sprachen auf dem gleichen Backend, der Vertipaq-Engine, arbeiten, so ist klar, dass die Parallelen von MDX zu DAX oder von Mengen-Konzepten zu DAX nicht nur theoretischer Art sind: MDX mit seinen Sets, Tupels und Membern ist quasi die native Sprache für das dimensionale Backend. Also kann man sich bei jeder Zeile DAX-Code auch fragen, welche Set-Operationen im Hintergrund eigentlich stattfinden.
Die Serie richtet sich an Anwender, die bereits die ersten Erfahrungen in DAX gesammelt haben und mit den von Marco Russo und Alberto Ferrari eingeführten Konzepten Filter, Context Transition und Filter Propagation etwas anfangen können. Vorteilhaft sind darüberhinaus auch Kenntnisse in SQL und / oder einer Objekt-Orientierten Sprache wie z.B. C#.

2. Grundoperation CrossJoin in der DAX-Funktion CROSSJOIN

Der Gedanke des CROSSJOINs besteht darin, jedes Element von Menge 1 mit jedem Element aus Menge 2 zu verknüpfen. Das Beispiel zeigt den CROSSJOIN für zwei 1-dimensionale Tuple-Sets. Set 1 enthält Buchstaben, Set 2 enthält Zahlen. Das Ergebnis der Verknüpfung ist ein 2-dimensionales Tupelset. Ein Set wird hier syntaktisch mit „{}“ dargestellt und ein Tupel mit „()“.
  • set1 = { A, B }
  • set3 = set1 CROSSJOIN set2
  • Inhalt von set3: { (A, 1 ), (A, 2), (A, 3), (B, 1), (B, 2), (B, 3) }
Figure 1 - DAX CROSSJOIN Function
Figure 1 - DAX CROSSJOIN Function
Die DAX-Funktion "CROSSJOIN" verhält sich wie in der Theorie erwartet, sie bildet das vollständige kartesische Produkt aus Region und City.

3. Grundoperation CrossJoin in der DAX-Funktion SUMMARIZECOLUMNS

Die Syntax von SUMMARIZECOLUMNS lautet:
  • SUMMARIZECOLUMNS (
  • <groupBy_columnName> [, < groupBy_columnName >]…,
  • [<filterTable>]…
  • [, <name>, <expression>]…)
Nur der erste Argument-Typ ist verpflichtend: Es müssen eine oder mehrere Gruppierungs-Spalten angegeben werden. Das nächste Beispiel zeigt den Einsatz von SUMMARIZECOLUMNS mit den entsprechenden Beispiel-Daten von oben. Es wird nur der erste verpflichtende Argument-Typ verwendet:
DAX-Beispiel / SUMMARIZECOLUMNS auf einem Snowflake-Schema.
Figure 2 - SUMMARIZECOLUMNS on a Snowflake-Schema
Figure 2 - SUMMARIZECOLUMNS on a Snowflake-Schema
Das Beispiel belegt, dass die Haupt-Operation von SUMMARIZECOLUMNS tatsächlich ein CROSSJOIN über die Gruppierungs-Spalten ist. Im Beispiel ist das Datenmodell hinter der DAX-Abfrage ein Snowflake-Schema. Die Entitäten „City“ und „Region“ sind dabei in separaten Tabellen abgelegt und über Relationships verbunden:
Figure 3 - Snowflake Schema
Figure 3 - Snowflake Schema
DAX-Beispiel / SUMMARIZECOLUMNS auf einem Star-Schema. Das nächste Beispiel zeigt wieder eine Abfrage mit SUMMARIZECOLUMNS und den gleichen Daten. Jedoch sind die Entitäten Region und City in denormalisierter Form bereit gestellt. Das Modell ist ein Star-Schema:
Figure 4 - Star Schema
Figure 4 - Star Schema
Die DAX-Abfrage führt jetzt zu einem anderen Ergebnis:
Figure 5 - Cross Matrix with Filter
Figure 5 - Cross Matrix with Filter
Es wurde jetzt nicht mehr die vollständige Kreuz-Matrix gebildet; „Berlin“ beispielsweise tritt nur noch zusammen mit der Region „North“ auf.
Regeln:
Bei CROSSJOIN wird – unabhängig vom Datenmodell – die vollständige Kreuz-Matrix bebildet
Bei SUMMARIZECOLUMNS wird optional die vollständige Kreuz-Matrix über Tabellen eingeschränkt, in der sich die Spalten befinden
Ablauf-Logik von SUMMARIZECOLUMNS:
1. Bilden einer vollständigen Kreuz-Matrix
2. Optional: Einschränken der Menge über Tabellen

4. SQL-Beispiel / Projektion von SUMMARIZECOLUMNS

Die beiden nachfolgenden Beispiele zeigen die Set-Operationen, wie man sie sich in SQL vorstellen kann.
SQL-Beispiel / Rückgabe einer vollständigen Kreuz-Matrix ohne Filter. Die Spalten-Werte stammen aus zwei verschiedenen Tabellen:
Figure 6 - SUMMARIZECOLUMNS on SQL
Figure 6 - SUMMARIZECOLUMNS on SQL
SQL-Beispiel / Rückgabe einer vollständigen Kreuz-Matrix mit Filter. Beachten Sie folgenden Unterschied zum vorausgegangenen Beispiel: Die Werte für „Region“ und „City“ stammen jetzt beide aus derselben Tabelle, nämlich "dimPerson1". Nachdem die vollständige Kreuzmatrix gebildet wurde, wird die Tabelle „dimPerson1“ benutzt, um nur die Tupels zurückgeben, die auch tatsächlich existieren.
Figure 7 - SUMMARIZECOLUMNS on SQL: Restrict CrossMatrix using a Filter Table
Figure 7 - SUMMARIZECOLUMNS on SQL: Restrict CrossMatrix using a Filter Table
Figure 7 - SUMMARIZECOLUMNS on SQL: Restrict CrossMatrix using a Filter Table
Die allgemeine Erkenntnis aus dem zweiten Beispiel ist, dass Tabellen eine Liste gültiger Tupels vorgeben, die zum Filtern anderer Sets verwendet werden können.