Tabulky jako filtry ve funkci CALCULATE

Power BI model

Ve funkci CALCULATE() můžeme používat jako filtry mimo jiné také tabulky. V tomto příspěvku jsou uvedeny jednoduché příklady s použitím tabulek jako filtrů. Bez ohledu na příklady uvedené v tomto příspěvku je důležité mít na paměti, že vždy když je to možné, je lepší použít ve funkci CALCULATE() logický filtr namísto filtru ve formě tabulky. V případě, že výpočet není možné vytvořit bez filtru ve formě tabulky, měli bychom použít ve filtru tabulku sestavenou pouze z těch sloupců, které jsou v dané situaci pro sestavení filtru nezbytně nutné. Používat ve filtru celou tabulku se všemi sloupci je obvykle špatná praxe jak z pohledu výkonu, tak z pohledu složitosti výpočtu. Čím méně sloupců v tabulce použité pro filtr ve funkci CALCULATE(), tím lepší výkon a jednodušší výpočet.

Příklady v tomto článku jsou vytvořeny ve cvičném souboru Adventure Works DW 2020.pbix, který je volně dostupný ke stažení na internetu. Soubor s řešením je dostupný ke stažení níže pod tímto příspěvkem.

V příkladech budeme pracovat s jednoduchým výpočtem, který bude vracet počet produktů z tabulky 'Product'.

Měřítko:

Počet produktů = COUNTROWS('Product')

Měřítko [Počet produktů] bude sloužit k porovnání výsledků s měřítky, jejichž výsledek budeme ovlivňovat pomocí různých tabulek. 

Filtr ve funkci CALCULATE ve formě tabulky

Dříve vytvořené měřítko, které počítá počet produktů z tabulky 'Product' v aktuálním kontextu vyhodnocení, můžeme vložit do tabulky s kategoriemi produktů v řádcích.

Tabulky jako filtry ve funkci CALCULATE

Měřítko [Počet produktů] vrací v každém řádku vizuálu počet produktů v dané kategorii. Nicméně ne každý produkt se v použitém modelu opravdu prodává. Jinak řečeno, v tabulce 'Produkt' jsou také produkty, které nemají záznam v tabulce prodejů 'Sales'. Pokud bychom chtěli zjistit počet produktů, které již mají záznam v tabulce 'Sales', tedy v tabulce obsahující záznamy o prodejích, můžeme v jazyku DAX použít následující definici měřítka.

Měřítko:

Počet produktů s prodeji =
CALCULATE
(
COUNTROWS('Product'),
Sales
)

Nové měřítko [Počet produktů s prodeji] má v prvním argumentu funkce CALCULATE() stejný výpočet jako měřítko [Počet produktů]. Tento výpočet je navíc při vyhodnocení ovlivněn filtrem, který obsahuje celou tabulku 'Sales'. Filtry ve funkci CALCULATE() jsou vyhodnoceny v originálním kontextu, ve kterém je funkce CALCULATE() vyvolána. Pokud tedy nové měřítko vložíme do dříve použitého vizuálu spolu s kategoriemi produktů v řádcích, tabulka 'Sales' obsahuje v každém řádku vizuálu pouze řádky odpovídající prodejům v dané kategorii. Takto zafiltrovaná tabulka 'Sales' je pak použita jako filtr při vyhodnocení prvního argumentu ve funkci CALCULATE().

Tabulky jako filtry ve funkci CALCULATE 2

Jak je možné vidět na obrázku výše, v tabulce 'Product' je 397 produktů, nicméně pouze 350 z nich má záznam o prodeji v tabulce 'Sales'. Pro pochopení, jak je přesně vyhodnoceno měřítko [Počet produktů s prodeji] je zapotřebí znát spoustu drobných detailů. Současně, takto vytvořený výpočet nemusí být optimální co se týká výkonu. Použití celé tabulky ve filtru funkce CALCULATE() je obvykle špatná praxe a měli bychom se těmto situacím vyhnout vždy, když je to možné. V použitém modelu můžeme namísto výpočtu v měřítku [Počet produktů s prodeji] daleko jednodušeji získat stejnou hodnotu pomocí funkce DISTINCTCOUNT(), vyvolané nad sloupcem s jedinečným identifikátorem produktů v tabulce 'Sales'.

Měřítko:

Počet produktů s prodeji (lepší verze) = DISTINCTCOUNT(Sales[ProductKey])

Nová verze výpočtu počtu produktů s prodeji vrací stejné výsledky jako měřítko [Počet produktů s prodeji], nicméně nová verze výpočtu je daleko jednodušší a obvykle bude takto vytvořené měřítko také rychleji vyhodnoceno.

Tabulky jako filtry ve funkci CALCULATE 3

Použití celé tabulky jako filtru ve funkci CALCULATE() není dobrá praxe. Tato technika byla často používaná ve starších verzích DAX Enginu, ve kterých nebyly dostupné všechny aktuálně dostupné funkce, a to pouze ve specifických případech. 

Filtry v CALCULATE ve formě tabulkových funkcí

Daleko užitečnější je pak použití filtrů ve funkci CALCULATE() ve formě funkcí vracející tabulky.  Typickým příkladem může být funkce FILTER(), která vrací tabulku uvedenou v prvním argumentu funkce obsahující pouze ty řádky, které odpovídají podmínce v druhém argumentu funkce. V podmínce definované ve funkci FILTER() můžeme použít všechny sloupce, které jsou součástí tabulky v prvním argumentu funkce. Pokud bychom například chtěli zobrazit počet produktů, které mají rozdíl mezi prodejní cenou a náklady větší než 500, můžeme použít následující výpočet.

Měřítko:

Počet produktů marže > 500 =
CALCULATE
(
    COUNTROWS('Product'),
    FILTER
    (
        'Product',
        'Product'[List Price] - 'Product'[Standard Cost] > 500
    )
)

Ve funkci FILTER() je použita opět tabulka se všemi sloupci, tentokrát tabulka 'Product'. Tato tabulka je opět vyhodnocena v kontextu filtru, ve kterém je funkce CALCULATE() vyvolána. To znamená, že pokud měřítko [Počet produktů marže > 500] vložíme do vizuálu s kategoriemi produktů v řádcích, v každém řádku bude při vyhodnocení měřítka tabulka 'Product' filtrována pouze na produkty v dané kategorii, a z těchto produktů budou dále vybrány pouze ty, které splňují podmínku definovanou ve druhém argumentu funkce FILTER(), tedy produkty, které mají ziskovou marži větší než 500.

Tabulky jako filtry ve funkci CALCULATE 4

Jak je možné vidět na obrázku výše, počet produktů, které mají rozdíl mezi cenou a náklady větší než 500, je celkem 102. V kategoriích Accessories a Clothing pak nejsou žádné produkty, které by splňovali podmínku definovanou ve funkci FILTER(). Pozorný čtenář již jistě ví, že předchozí měřítko [Počet produktů marže > 500] nesplňuje podmínku dobré praxe v jazyku DAX, a to použití co nejméně sloupců ve filtru funkce CALCULATE(). Funkce FILTER() sice omezuje počet řádků, ale ne počet sloupců. Ve filtru funkce CALCULATE() bychom ale měli používat pouze sloupce nezbytně nutné.

Filtry ve formě tabulek s použitím co možná nejméně sloupců

V následujícím výpočtu je ve funkci FILTER() použita v prvním argumentu jiná funkce vracející tabulku, a to funkce SUMMARIZE(). Výsledkem funkce SUMMARIZE() jsou pouze dva sloupce uvedené ve druhém a třetím argumentu této funkce. Jedná se o jediné dva sloupce, které jsou potřebné pro sestavení filtru a jde tedy o výpočet, který bude ve většině případů vyhodnocen rychleji než výpočet předchozí.

Měřítko:

Počet produktů marže > 500 (lepší verze) =
CALCULATE
(
COUNTROWS('Product'),
FILTER
(
SUMMARIZE
(
'Product',
'Product'[List Price],
'Product'[Standard Cost]
),
'Product'[List Price] - 'Product'[Standard Cost] > 500
)
)

Prvním argumentem funkce FILTER() již tedy není celá tabulka 'Product', jako tomu bylo u původní verze měřítka, ale funkce SUMMARIZE(), která vrací pouze existující kombinace hodnot ze sloupců 'Product'[List Price] a  'Product'[Standard Cost]. Výsledná tabulka ve filtru měřítka [Počet produktů marže > 500 (lepší verze)] má tedy pouze dva sloupce, které obsahují hodnoty platné pro podmínku definovanou ve druhém argumentu funkce FILTER(), s ohledem na aktuální kontext vyhodnocení

Tabulky jako filtry ve funkci CALCULATE 5

Výsledky obou verzí měřítek jsou v aktuálním kontextu stejné, nicméně nová verze měřítka by měla být preferována, protože ve výpočtu není použitá celá tabulka 'Product', ale pouze sloupce nezbytně nutné pro sestavení filtru.

Pokud používáme k sestavení filtru sloupce z jedné tabulky, můžeme se tabulkovým filtrům ve funkci CALCULATE() vyhnou úplně a vytvořit pouze logickou podmínku ve funkci CALCULATE() následujícím způsobem.

Měřítko:

Počet produktů marže > 500 (logický filtr) =
CALCULATE
(
    COUNTROWS('Product'),
    KEEPFILTERS
    (
        'Product'[List Price] - 'Product'[Standard Cost] > 500
    )
)

Výsledek je opět stejný jako předchozí výpočty, nicméně tentokrát s použitím logického filtru namísto filtru ve formě tabulky.

Tabulky jako filtry ve funkci CALCULATE 6

Co se týká dobré praxe, logický filtr by měl být opět preferovanou variantou před filtrem ve formě tabulky. Logické filtry jsou sice na pozadí převedeny také na tabulky, jak se můžete dozvědět v tomto příspěvku, nicméně pro autora DAX kódu se jedná o jednodušší způsob používání filtrů.

Shrnutí

Vždy, když je to možné a můžeme použít ve funkci CALCULATE() logický filtr namísto filtru ve formě tabulky, měli bychom použít právě logický filtr, který bude pravděpodobně vyhodnocen rychleji a současně se vyhneme případným neočekávaný výsledkům způsobeným komplexností filtrů ve formě tabulek. V některých příkladech může být použití filtru ve formě tabulky nezbytné pro dosažení požadovaného výsledku. Pokud je pro dosažení požadovaného výsledku nezbytné použít jako filtr tabulku, měli bychom se snažit sestavit ve filtru tabulku pouze s těmi sloupci, které jsou pro ovlivnění výsledku v prvním argumentu funkce CALCULATE() nezbytně nutné. Praktické příklady, některé také s použitím tabulek jako filtrů ve funkci CALCULATE(), můžete najít na stránce DAX - Příklady nebo na stránce Power BI - Příklady.

č. 31

Komentáře