In Power BI kann man die Richtung beeinflussen, wie Filter zwischen Tabellen propagiert werden. In unseren Trainings raten wir davon ab, diese Kreuzfilter-Richtung zu ändern. Aber warum eigentlich? Weil man damit früher oder später in die Hölle kommt...

Disclaimer

Der folgende Artikel ist nicht leicht zu verstehen - aber wir glauben: er lohnt sich! Es lohnt sich zu verstehen, warum das mit der bidirektionalen Kreuzfilter-Richtung einfach keine so gute Idee ist. Du hast andere Gründe, warum du diese Funktionalität trotzdem benötigst? Wir freuen uns sehr über Kommentare!

Die Kreuzfilter-Richtung

Wenn man in Power BI ein Datenmodell aufbaut, sollte man verstanden haben, wie eine Tabelle auf der 1-Seite eine Tabelle auf der *-Seite filtert. In den verschiedenen Versionen von Excel Power Pivot und später Power BI wurde die Darstellung einer Beziehung immer ein wenig angepasst. In Power BI wird jetzt neben der Kardinalität auch die Richtung dargestellt, wie Filter propagiert werden:

Beziehung mit Kreufilterrichtung in Power BI

Diese Richtung kann man in Power BI (anders als in Excel Power Pivot) in beide Richtungen, also bidirektional konfigurieren. Dazu öffnet man via Doppelklick (oder Kontextmenü) den Eigenschaftsdialog der Beziehung und passt unten rechts die Kreuzfilter-Richtung auf Beide.

Kreuzfilter-Richtung konfigurieren

Die Filter-Richtung auf der Beziehung wird jetzt in beide Richtungen dargestellt.

Bidirektionaler Kreuzfilter in Power BI

Wozu ändert man überhaupt die Kreuzfilter-Richtung?

Dafür gibt es sicher viele Gründe - zwei sind mir am geläufigsten:

  • Power BI hat die Beziehung automatisch angelegt und hat entschieden, die Kreuzfilter-Richtung bidirektional anzulegen (im Normalfall mit vielen anderen fehlerhaften Beziehungen, die dann nach und nach gelöscht werden müssen)
  • Der Benutzer hat eine DrillThrough-Page für Faktendaten angelegt und möchte Dimensionsdaten als Zusatzinformation anzeigen - und das war eben der einfachste Weg

Zum zweiten Grund: die DrillThrough-Page

Ich möchte hier nicht detailliert auf DrillThrough-Pages eingehen. Aber stellen wir uns vor, in einem Report sollen Auftrags-Detaildaten angezeigt werden. In der Detail-Seite sollen also Auftragsnummer, Umfang und beispielsweise ein Artikel angezeigt werden. Die Faktentabelle kennt aber nur die ArtikelID - also den Schlüssel auf die entsprechende Dimensionstabelle. Natürlich möchte man zum Artikel mindestens die Bezeichnung anzeigen. Das klappt aber nicht, da eine Faktentabelle seine Dimensionstabellen nicht filtert. Oder konkret: die Tabelle Auftrag filter die Tabelle Artikel oder Standort nicht,

Nur mit Power BI Bordmitteln (also ohne DAX) erreicht man das nur durch bidirektionale Kreuzfilterung.

Beispiel-Dashboard

Betrachten wir folgendes Beispiel-Dashboard:

Power BI Beispiel Dashboard

Ein Unternehmen hat mehrere Standorte. Die Standorte verkaufen Artikel, die zu Artikelgruppen zusammengefasst wurden. Jeder Standort hat einen lokalen Lagerbestand. Das Dashboard zeigt den Umsatz pro Standort, die Aufträge, Bestände pro Artikelgruppe und pro Artikel sowie den Umsatz pro Artikelgruppe.

Bestände pro Artikelgruppe und Bestände pro Artikel darzustellen hat den Charme, dass via Crossfilterung durch Auswahl einer Artikelgruppe in der linken Tabelle die zugehörigen Artikel und deren Bestände in der rechten Tabelle Artikel-Bestand dargestellt werden. Die Gesamtsummen beider Tabellen sollten übereinstimmen. Wird eine Artikelgruppe selektiert, sollte die Gesamtsumme von Artikel-Bestand mit dem Bestand der gewählten Artikgelgruppe übereinstimmen.

Der Fehler

Wählen wir die Artikelgruppe 1, erhalten wir dieses Ergebnis:

Beispiel einer Kreuzfilter-Anomalie

Der Bestand der Artikelgruppe beträgt 145, der Gesamtbestand der einzelnen Artikel ebenfalls. Nur ergibt die Zeilensumme eigentlich 132 und nicht 145!

Die Kreuzfilter-Hölle

Ich kann nicht genug betonen, dass man die Kreuzfilter-Richtung nur ändern sollte, wenn man genau weiß, was man tut und dies bei späteren Änderungen am Datenmodell auch im Blick behält. Meist ist es so, dass man wusste, was man tut - und dann ist das Datenmodell gewachsen. Daher: Am besten tut man es einfach nicht!

Das Datenmodell dieses Beispiels sieht folgendermaßen aus:

Power Bi Datenmodell mit bidirektionaler Kreuzfilter-Richtung

Zwischen Auftrag und Standort ist die Kreuzfilter-Richtung bidirektional. Vielleicht, weil man eben eine DrillThrough-Page für Aufträge hatte. Und dort wollte man den Standortnamen darstellen.

Und später hat man dann Lagerbestände eingeführt - und mit dem Standort verbunden. Ohne zu beachten, dass die Kreuzfilter-Richtung hier Einfluss auf die Ergebnisse hat.

Wie entsteht dieser Fehler

Wenn die Artikelgruppe gefiltert wird in der Tabelle Artikelgruppen-Bestand, dann filtert Power BI alle Artikel, die zur Gruppe gehören. Dieser Filter wird in die Tabelle Lagerbestand propagiert. Der Filter wird aber auch in die Tabelle Auftrag propagiert. Dort werden alle Aufträge mit Artikeln dieser Gruppe gefiltert. Konkret sind das folgende Aufträge:

Power Bi Auftraege in Demo Dashboard

Alle anderen Aufträge sind nur Verschleierung und haben mit unserem konkreten Problem nichts zu tun.

Es werden also die Artikelnummern 1 und 2 gefiltert. Diese wurden von Standort 1 und 2 bestellt. Dieser Filter wird an die Tabelle Standort weitergereicht - weil wir haben eine bidirektionale Filterung eingestellt.

Die Tabelle Standort filtert jetzt gleichzeitig mit der Tabelle Artikelgruppe und Artikel die Tabelle Lagerbestand - zusätzlich werden also die Standorten 1 und 2 gefiltert. obwohl das gar nicht gewollt ist.

Die Tabelle Lagerbestand hat folgende relevanten Einträge:

Power BI Lagerbestand im Datenmodell

Gefiltert sind die Artikel 1 und 2 sowie die Standorte 1 und 2 - damit erhalten wir den Bestand 145. Ein Fehler tritt hier also nicht auf.

In der Tabelle Artikel-Bestand werden die Bestände der Artikel der gewählten Gruppe einzeln dargestellt. Was passiert hier: Für jeden Artikel in der Tabelle Artikel die zur Gruppe 1 gehören wird eine Zeile erzeugt. Für jede Zeile wird jetzt ein Artikel-Filter propagiert. Artikel 1 wird korrekt dargestellt - hier scheinen wir kein Problem zu haben. Es fehlt aber Artikel 2.

Wo ist Artikel 2?

In der zweiten Zeile der Tabelle haben wir Artikel 2 "in der Hand". Artikel 2 filtert die Tabelle Lagerbestand. Als Ergebnis erhalten wir eine Zeile mit folgenden Werten:

Tabelle Lagerbestand mit ArtikelID=2

Gleichzeitig filtert der Artikel (also Artikel 2) die Auftragstabelle. Dort erhalten wir mit dem Artikel 2 einen Auftrag:

Tabelle Auftragstabelle mit ArtikelID=2

In der Auftragstabelle bleibt also genau ein Auftrag übrig - mit Standort=1. Dieser Standort wird über die bidirektionale Kreuzfilter-Richtung an die Standort-Tabelle propagiert - und dadurch auch an die Tabelle Lagerbestand.

Die Tabelle Lagerbestand ist aber bereits durch den Artikel gefiltert und es bleibt nur eine Zeile übrig - mit anderem Standort, nämlich Standort 2. Jetzt kommt ein zusätzlicher Filter Standort = 2 aus der Tabelle Standort hinzu. Das Ergebnis ist damit leer. Der Artikel wird in der Tabelle nicht mehr aufgeführt.

Warum stimmt dann die Gesamtsumme?

Die Zeilen der Tabelle werden mit den Filtern der jeweiligen Zeile berechnet, also in unserem Fall die Artikelnummer. Die Gesamtsumme wird ohne diesen Filter gebildet. Da ohne den Artikel-Einzelfilter beide Standorte in der Auftragstabelle vorkommen, wird der Bestand korrekt angezeigt. Sonst wäre der Bestand in der linken Tabelle Artikelgruppen-Bestand auch schon fehlerhaft.

Achtung: In diesem Fall sieht man die Inkonsistenz. Wäre aber der Bestand der Artikelgruppe schon fehlerhaft, weil beide Artikel von anderen Standorten verkauft wurden, als sie aktuell gelagert sind (und das ist ja fachlich absolut vorstellbar), dann sind die Zahlen im Dashboard konsistent. Konsistent aber falsch!

Es ist meistens komplizierter

Diese Konstellation ergibt sich aus Beispieldaten. Schon hier ist der Umstand schwierig genug nachzuvollziehen. In einem echten Datenmodell kann diese Konstellation auch dadurch entstehen, dass Aufträge durch Filterung beispielsweise des Auftragsdatums eingeschränkt werden. Und durch diese Konstellation gibt es dann vielleicht keinen Auftrag für einen Artikel mit einem bestimmten Standort - und nur in dieser Konstellation kommt es dann zu Fehlern.

Die Fehler sind insbesondere mit vielen Daten schwierig zu finden oder auch nachzuvollzuiehen, da alle Standorte meist kontinuierlich Waren verkaufen und die fehlerhaften Konstellationen nicht sofort sichtbar sind.

Fazit

Abhilfe ist einfach: Nutzt keine bidirektionalen Kreuzfilter! Auch wenn es ein anderes Problem scheinbar kurzfristig löst. Um beim Beispiel der DrillThrough-Page zu bleiben: Um hier den Standort anzuzeigen baut man sich eben eine Measure: