Blog Article & Copyright by Lukas Hillesheim
In der DAX-Sprache kann Sortierung erst am Schluss - bei der Ausgabe der Daten - angewandt werden, nicht jedoch zwischendurch, um beispielsweise Ergebnisse von Teil-Operationen als sortierte Menge in Variablen abzulegen. Der folgende Artikel zeigt, wie dieses Ziel mit der Hilfe von GENERATE und GENERATESERIES erreicht werden kann.
Der Artikel verwendet ein Beispiel mit dem folgenden Aufbau:
- - Schritt 1: Eine Variable "set0_RankedCities" wird mit einer Liste von Städte-Namen, deren Umsatz und einer entsprechenden Rank-Information gefüllt.
- - Schritt 2: Der Inhalt von "set0_RankedCities" wird in eine weitere Variable namens "set1_SortedCities" kopiert. Der Kopiervorgang erfolgt im Rahmen einer ForEach-Schleife, die pro Schleifen-Durchgang das Element mit dem aktuellen Rank findet und in das Ergebnis einfügt. Da die Schleife eine Suche der Ranks in aufsteigender Reihenfolge bewirkt, ergibt sich im Ergebnis eine Sortierung nach Rank. Die zweite Variable enthält somit den sortierten Inhalt der ersten Variablen.
- - Schritt 3: Der Inhalt der zweiten Variablen, "set1_SortedCities", wird in einer Spalte als konkatenierter String ausgegeben. Beachten Sie, dass der in sich sortierte String nicht mit ORDER BY generiert werden könnte.
1. Erzeugen einer Liste mit Rank-Information
Ausgangspunkt ist eine unsortierte Liste mit Städten, deren Umsatz und eine einer entsprechenden Rank-Information. Die Rank-Information implementiert das bentzerdefinierte Sortierungs-Kriterium und wird später wie ein Index verwendet. Anbei DAX-Code und Output:
Liste der Städte mit Rank (jedoch nicht sortiert nach dem Rank):
2. Erzeugen einer sortierten Liste
Die sortierte List wird mit folgendem Ausdruck erzeugt:
Die Grundidee besteht darin, eine ForEach-Schleife in DAX nachzubilden und durch das erste Argument - die Collection - zu steuern, in welcher Reihenfolge die Elemente ausgewählt werden. Pro Schleifendurchgang soll eine bestimmte Zeile aus der Quell-Menge extrahiert werden und in das Ergebnis - die Variable "set1_SortedCustomers" - eingefügt werden.
- - GENERATE ist das DAX-Pendant zu einer ForEach-Schleife
- - GENERATESERIES wird als erstes Argument für GENERATE verwendet und ist dafür zuständig, den ersten Teil der Schleife, die Collection, festzulegen
- - FILTER wird als zweites Argument für GENERATE verwendet und entspricht dem Block, der pro Schleifendurchgang ausgeführt wird
Vergleich zwischen GENERATE und einer OOP-basierten Schleife:
- GENERATE ( // ForEach (...)
- <set1>, // ForEach ( <item> in <collection> )
- <set2> ) // ForEach ( <item> in <collection> ) { <operation> }
Im konkreten Beispiel soll über eine Integer-Liste iteriert werden. Die Integer-Liste soll die Liste der Rank-Values widerspiegeln. Beispielsweise enthält die Liste der Städte 8 Elemente, die entsprechend von 1 bis 8 gerankt sind. Daher soll das erste Argument für GENERATE eine Liste der Ganzzahlen von 1 bis 8 sein. Diese Liste wird mit GENERATESERIES erzeugt.
Beachten Sie, dass das Ergebnis von GENERATESERIES eine Spalte namens [Value] enthält. Auf diese Spalte wird in späteren Code-Zeilen verwiesen.
Die Ganzzahl-Liste soll bei 1 starten. Der Upperbound - der Endwert - soll dynamisch festgelegt werden und der Anzahl der Elemente in der Liste der Städte entsprechen. Hierfür wird COUNTROWS verwendet.
Das zweite Argument von GENERATE ist ebenfalls ein Mengen-Ausdruck, der pro Schleifendurchgang evaluiert wird. Mit Hilfe von FILTER werden aus der Liste der Städte alle Städte extrahiert, deren Rank identisch mit dem Wert des Schleifenzählers sind. Da die Rank-Werte auf Grund der Option "DENSE" eindeutig sind, wird pro Schleifendurchgang exakt eine Stadt gefunden und in das Ergebnis eingefügt.
3. Ausgabe der sortierten Liste als konkatenierter String
Die Ausgabe einer sortierten Liste gehört nicht zum Lösungs-Ansatz, sondern soll quasi als Beweis veranschaulichen, dass die Sortierung VOR der Ausgabe passiert: