Slicer von ODER- zu UND-Logik ändern in Power BI

January 16, 2022
Denis Selimovic
DAXcomment 3Created with Sketch Beta.0 comments

This post is also available in: Englisch

In Power BI haben Slicer generell eine ODER-Logik implementiert. Dies ich im Normalfall auch genau das, was der User haben möchte. Wenn ich in einem Slicer die Jahre 2021 und 2022 selektiere, dann möchte ich im Ergebnis die Werte betrachten, welche entweder dem Jahr 2021 oder dem Jahr 2022 zuzuordnen sind.

ODER-Logik nicht immer die richtige

Gelegentlich gibt es allerdings Situationen, in denen das nicht das gewünschte Verhalten ist. Nehmen wir mal an, wir möchten Kunden ermitteln, welche “Produkt A” und gleichzeitig “Produkt C” gekauft haben. In so einem Fall würde ich gerne beide Produkte in dem Slicer auswählen. Als Ergebnis sollen in einer Tabelle aber nur diese Kunden angezeigt werden, welche beide Produkte gekauft haben.
Für solch einen Fall benötige ich eine UND-Logik für meinen Slicer.

Grundsätzlich lässt sich die Logik des Slicers nicht ändern. Ich kann eine UND-Logik allerdings mit einem Measure nachbilden und dann entweder nur das gewünschte Ergebnis zurückliefern oder ein Visual mit dem Measure filtern.

Beispiel Szenario – Welcher Herr der Ringe Charakter hat welche Waffen

Als heutiges Beispiel nehmen wir unsere Charaktere aus Herr der Ringe. Wir würden gern wissen, welcher Charakter verwendet welche Waffe. Jeder Charakter kann mehrere Waffen haben und dies würden wir gerne über einen UND-Filter abbilden.

Hier die Übersicht, welcher Charakter welche Waffen besitzt:

Übersicht Charaktere und deren Waffen
Übersicht Charaktere und deren Waffen

Unser Datenmodell ist ebenfalls recht einfach gehalten für dieses Szenario. Wir haben die 2 Dimensionstabellen ‘Person’ und ‘Weapon’ sowie die Faktentabelle ‘Fact’:

Datenmodell für ODER Slicer
Datenmodell für ODER-Slicer

Als ersten Schritt erstellen wir ein Measure und speichern uns als Variable die im Slicer ausgewählten Werte mit der ALLSELECTED Funktion, sowie die Anzahl im Slicer ausgewählter Elemente.

Filter AND Weapon = 
-- Get the chosen weapons from the slicer
VAR vSlicerSelection = ALLSELECTED ( Weapon[Weapon] ) 
-- Count the amount of chosen weapons fromt the slicer
VAR vAmountSelected = COUNTROWS ( vSlicerSelection )

Da wir die Waffen pro Person haben möchten, verwenden wir die VALUES Funktion, um die einzelnen Personen aufzulisten und fügen in die virtuelle Tabelle die Anzahl Waffen mit der Funktion ADDCOLUMNS hinzu:

-- Calculate the amount of weapons per person
VAR vWeaponsPerCharacter =
    ADDCOLUMNS (
        VALUES ( Person[Name] ),
        "@NumberWeapons",
            CALCULATE (
                DISTINCTCOUNT ( 'Fact'[WeaponID] ),
                KEEPFILTERS ( vSlicerSelection ),
                ALL ( Weapon )
            )
    

Danach müssen wir nur noch die Anzahl Waffen für die aktuelle im Filterkontext befindliche Person herausfinden:

-- Return the number of weapons per person
VAR vNumberWeapons = MAXX ( vWeaponsPerCharacter, [@NumberWeapons] )

Als letzten Schritt müssen wir dies mit der Anzahl gewählten Optionen im Slicer vergleichen. Wenn im Slicer 2 Waffen gewählt wurden und die Person im aktuellen Filterkontext besitzt 2 Waffen, dann bedeutet es, dass sie beide gewählten Waffen besitzt. Entsprechend soll die Person angezeigt werden.

Hierzu gebe ich eine 1 zurück. Falls die Person weniger Waffen hat eine 0.

-- If the number of the current person is equal to the number of selected items or if no selection is done
-- then return 1, otherwise return 0
VAR vResult =
    IF (
        vNumberWeapons = vAmountSelected || vAmountSelected = COUNTROWS ( ALL ( Weapon[Weapon] ) ),
        1,
        0
    )

Zum Schluss müssen diese einzelnen Blöcke einfach noch in ein Measure kombiniert werden:

Filter AND Weapon = 
-- Get the chosen weapons from the slicer
VAR vSlicerSelection = ALLSELECTED ( Weapon[Weapon] ) 
-- Count the amount of chosen weapons fromt the slicer
VAR vAmountSelected = COUNTROWS ( vSlicerSelection )
-- Calculate the amount of weapons per person
VAR vWeaponsPerCharacter =
    ADDCOLUMNS (
        VALUES ( Person[Name] ),
        "@NumberWeapons",
            CALCULATE (
                DISTINCTCOUNT ( 'Fact'[WeaponID] ),
                KEEPFILTERS ( vSlicerSelection ),
                ALL ( Weapon )
            )
    )
-- Return the number of weapons per person
VAR vNumberWeapons = MAXX ( vWeaponsPerCharacter, [@NumberWeapons] )
-- If the number of the current person is equal to the number of selected items or if no selection is done
-- then return 1, otherwise return 0
VAR vResult =
    IF (
        vNumberWeapons = vAmountSelected || vAmountSelected = COUNTROWS ( ALL ( Weapon[Weapon] ) ),
        1,
        0
    )
-- return the result
RETURN
    vResult

Dieses Measure können wir zur Filterung des entsprechenden Visuals verwenden. Somit ändern wir das Verhalten von einem ODER- zu einem UND-Slicer:

Slicer von ODER- zu UND-Slicer ändern
Slicer von ODER- zu UND-Slicer ändern

Die Beispieldatei kann hier heruntergeladen werden: