DAX funkce SWITCH

Funkce SWITCH() porovnává hodnotu nebo výraz v prvním argumentu se zadaným seznamem hodnot v dalších argumentech a vrací výsledek, který odpovídá první shodné hodnotě z definovaného seznamu. Při zadávání seznamu hodnot je proto důležité pořadí. V tomto příspěvku si na několika příkladech vytvořených v Power BI vysvětlíme jak funkce SWITCH() funguje a jak můžeme tuto funkci používat v různých typech výpočtů.

K tomuto tématu je k dispozici také video:

Funkce SWITCH() je při vyhodnocení na pozadí transformována na alternativní kód ve formě vnořených IF() výrazů. Stejná logika vytvořená pomocí funkce SWITCH() proto nebude vyhodnocena rychleji než alternativní kód napsaný pomocí vnořených IF(). Používání SWITCH() namísto vnořených IF() funkcí však může výrazně zjednodušit psaní a přehlednost DAX kódu.

Příklady v tomto příspěvku jsou vytvořeny ve cvičném Power BI souboru Contoso Sales Sample for Power BI Desktop.pbix., který je volně dostupný ke stažení na internetu. Soubor s řešenými je k dispozici ke stažení níže pod tímto příspěvkem.

Počeštěná syntaxe funkce SWITCH() vypadá následovně.

Syntaxe funkce SWITCH:

SWITCH     (         <výraz>,         <hodnota k porovnání>,<vrácená hodnota>         [,<hodnota k porovnání>, <vrácená hodnota>]…         [, <alternativní výsledek>]     )

Prvním argumentem funkce SWITCH() je jakýkoliv výraz vracející skalární hodnotu. Další argumenty se zadávají vždy v páru, a to hodnota k porovnání a výsledná hodnota vrácená v případě shody. Těchto argumentů můžeme zadat libovolné množství. Pokud zadaný výraz v prvním argumentu nebude nalezen v seznamu hodnot pro porovnání, výsledkem bude alternativní výsledek, což je nepovinný argument a v případě jeho nevyplnění je tento argument defaultně nastaven na prázdnou hodnotu BLANK.

Příklady funkce SWITCH

Na prvním jednoduchém příkladu si ukážeme, jak funkce SWITCH() funguje a jakým způsobem je na pozadí funkce SWITCH() vyhodnocena pomocí vnořených IF() funkcí. To je důležité pro pochopení toho, proč je pořadí zadaných argumentů v určitých typech výpočtů důležité pro dosažení požadovaného výsledku.

Rozdíl mezi SWITCH a vnořenými IF

V použitém cvičném Power BI souboru je v tabulce 'Stores' 306 obchodů, které jsou zařazeny do čtyř kategorií.

DAX funkce SWITCH

Sloupec 'Stores'[StoreType] obsahuje anglické názvy typů obchodů. Pokud bychom chtěli vytvořit v tabulce 'Stores' sloupec s alternativními českými názvy typů obchodů, můžeme použít následující definici počítaného sloupce s použitím funkce SWITCH().

Počítaný sloupec:

Typ obchodu =
SWITCH
(
    Stores[StoreType],
    "Store", "Kamenná prodejna",
    "Reseller", "Překupník",
    "Catalog", "Katalogové prodeje",
    "Online", "Internetový obchod",
    "Jiné"
)

Prvním argumentem funkce SWITCH() je název sloupce, ze kterého budeme v každém řádku tabulky načítat aktuální typ obchodu. Tato hodnota bude v každém řádku tabulky načtena a porovnána se seznamem hodnot, které jsou zadané ve druhém a dalších sudých argumentech funkce SWITCH(). Pokud bude hodnota ve sloupci 'Stores'[StoreType] v aktuálním řádku tabulky shodná s některou hodnotou ze seznamu hodnot, výsledek bude odpovídající český překlad. V situaci, kdy by žádná hodnota ze seznamu hodnot neodpovídala aktuální hodnotě ve sloupci 'Stores'[StoreType], výsledkem bude alternativní výsledek, který ve výše uvedeném výpočtu obsahuje hodnotu "Jiné".

Výsledkem je nový počítaný sloupec s českými popisy typů obchodů.

DAX funkce SWITCH 2

Pokud bychom chtěli dosáhnout stejného výsledku s použitím vnořených IF() funkcí, výpočet by mohl vypadat následovně.

Počítaný sloupec:

Typ obchodu (vnořené IF funkce) =
IF
(
    Stores[StoreType] = "Store",
    "Kamenná prodejna",
    IF
    (
        Stores[StoreType] = "Reseller",
        "Překupník",
        IF
        (
            Stores[StoreType] = "Catalog",
            "Katalogové prodeje",
            IF
            (
                Stores[StoreType] =  "Online",
                "Internetový obchod",
                "Jiné"
            )
        )
    )
)

Tato druhá definice počítaného sloupce sice vrací stejné výsledky, nicméně zápis je méně přehledný, a proto také náchylnější na případné chyby. Tato druhá varianta výpočtu je pro nás ale důležitá pro pochopení toho, jak funkce SWITCH() funguje. 

Každý výpočet vytvořený pomocí funkce SWITCH() je totiž na pozadí vyhodnocen jako vnořené IF() funkce. Funkce IF() má v prvním argumentu podmínku, a vrací druhý argument v případě že je podmínka splněna, a třetí argument v případě že podmínka není splněna. To je přirozené, intuitivní a dobře známé chování funkce IF(). Důležité je si ale uvědomit, že pokud je splněna podmínka zadaná v prvním argumentu funkce IF(), bude výsledkem druhý argument funkce, a třetí argument funkce IF() již nebude vyhodnocen. 

Vrátíme-li se pak k funkci SWITCH(), tak výsledkem této funkce bude první argument, pro který bude splněna podmínka, a případné další argumenty této funkce již nebudou v případě shody v předchozím argumentu nikdy vyhodnoceny. Pro určité typy výpočtů je proto důležité také pořadí, v jakém zadáváme jednotlivé argumenty do funkce SWITCH(), jak si ukážeme v následujícím příkladu.

Rozdělení záznamů do kategorií pomocí funkce SWITCH

Funkci SWITCH() se často používá pro roztřídění hodnot do kategorií. Pokud bychom například chtěli rozdělit obchody do kategorií podle počtu zaměstnanců, které jsou uloženy ve sloupci 'Stores'[EmployeeCount], můžeme vytvořit v tabulce 'Stores' nový počítaný sloupec s následujícím kódem.

Počítaný sloupec:

Počet zaměstnanců =
SWITCH
(  
    TRUE(),
    Stores[EmployeeCount] <= 15, "0 - 15",
    Stores[EmployeeCount] <= 30, "16 - 30",
    Stores[EmployeeCount] <= 50, "31 - 50",
    Stores[EmployeeCount] <= 100, "51 - 100",
    Stores[EmployeeCount] <= 200, "101 - 200",
    "201 - " & MAX(Stores[EmployeeCount])
)

Prvním argumentem výše uvedeného výpočtu je nyní funkce TRUE(), která jednoduše vrací hodnotu TRUE a výsledkem proto bude první kategorie, pro kterou bude splněna podmínka zadaná v seznamu hodnot. Pokud bude například počet zaměstnanců ve sloupci 'Stores'[EmployeeCount] menší nebo roven hodnotě 15, výsledkem bude kategorie "0 - 15". Ve druhé podmínce ověřujeme, zda je hodnota ve zdrojovém sloupci menší nebo rovna hodnotě 30. U této druhé podmínky je dobré zpomalit a zamyslet se nad touto definicí. 

Druhá podmínka totiž neobsahuje ověření spodní hranice. To si můžeme dovolit právě díky tomu, že pokud by počet zaměstnanců byl menší než 16, druhá podmínka by nikdy nebyla vyhodnocena, protože by již byla splněna první podmínka a výsledkem by byla kategorie "0 - 15". Z tohoto důvodu, pokud dodržíme správné pořadí jednotlivých podmínek, nemusíme v žádné následující podmínce ověřovat spodní hranici pro danou kategorii. 

Tento typ výpočtu je proto klasickým příkladem kdy samotné pořadí zadaných podmínek může ovlivňovat výsledek výpočtu. Pokud bychom totiž zadali podmínky v jiném pořadí, výsledky by již nebyly správné. Jinak řečeno, podmínku <= 200 splňuje obchod s 15, 30, 50 nebo 170 zaměstnanci. To že obchod s 15 zaměstnanci bude v kategorii "0 - 15" je proto, že tato kategorie je vyhodnocena jako první a další podmínky již pro tento konkrétní obchod nebudou vyhodnoceny. V příkladu s rozdělením obchodů do kategorií podle počtu zaměstnanců proto začínáme od kategorie s nejnižším počtem zaměstnanců a pokračujeme až po kategorii s nejvyšším počtem zaměstnanců.

DAX funkce SWITCH 3

Další variantou použití funkce SWITCH() může být následující ukázka, kdy každá podmínka obsahuje další dvě vnořené podmínky spojené operátorem AND (&&).

Počítaný sloupec:

Velikost kamenné prodejny =
SWITCH
(
    TRUE(),
    Stores[StoreType] = "Store" && Stores[EmployeeCount] <= 30, "Malá kamenná prodejna",
    Stores[StoreType] = "Store" && Stores[EmployeeCount] <= 70, "Střední kamenná prodejna",
    Stores[StoreType] = "Store", "Velká kamenná prodejna"
)

Prvním argumentem funkce SWITCH() je opět funkce TRUE() vracející hodnotu TRUE. Výsledkem funkce proto bude opět první hodnota ze zadaného seznamu hodnot, u které bude zadaný logický výraz vracet právě hodnotu TRUE. 

Výsledkem nového počítaného sloupce bude hodnota "Malá kamenná prodejna", pokud je typ obchodu roven hodnotě "Store" a současně je počet zaměstnanců menší nebo roven hodnotě 30. Středně velká kamenná prodejna musí splňovat podmínku pro počet zaměstnanců 31 - 70. Pokud je počet zaměstnanců větší než 70 a zároveň se jedná o typ prodejny "Store", bude výsledkem hodnota "Velká kamenná prodejna". V případě kdy nebude splněna žádná z podmínek, to znamená pokud se bude jednat o jakýkoliv jiný typ obchodu než je typ obchodu "Store", výsledkem funkce SWITCH() bude prázdná hodnota BLANK, protože argument s alternativním výsledkem není ve výše uvedeném výpočtu vyplněn.

DAX funkce SWITCH 4

Na obrázku výše je možné vidět výsledek nového počítaného sloupce v Power BI vizuálu. Funkci SWITCH() však můžeme používat také měřítku, jak si ukážeme v následujícím příkladu.

Funkce SWITCH v měřítku

Funkci SWITCH() můžeme samozřejmě používat také pro vyhodnocení podmínek v měřítku. Příkladem může být vizuál Matice, kde jsou v řádcích kategorie, podkategorie a produkty. V hodnotách chceme zobrazit sumu prodejů v různých jednotkách podle aktuální úrovně v hierarchii. Jelikož každá kategorie zahrnuje spoustu prodaných produktů, budou hodnoty pro kategorii zobrazeny v milionech. Pro podkategorii budou hodnoty zobrazeny v tisících a pro jednotlivé produkty v korunách. Výsledek může vypadat následovně.

DAX funkce SWITCH 5

Ve druhém sloupci na obrázku výše můžeme vidět měřítko [Prodeje], které vrací sumu za prodané produkty v originálních hodnotách. Ve třetím sloupci vizuálu je měřítko [Prodeje (formát podle aktuální úrovně)], ve kterém převádíme hodnotu prodejů na různé jednotky podle toho, v jaké úrovni hierarchie je měřítko vyhodnoceno. Samotný výpočet pomocí s použitím SWITCH() může vypadat následovně.

Měřítko:

Prodeje (formát podle aktuální úrovně) =
VAR Prodeje = [Prodeje]
VAR Vypocet =
    SWITCH
    (
        TRUE(),
        ISINSCOPE('Product'[ProductName]), FORMAT(Prodeje, "#,##0.00 Kč", "cs-cz"),
        ISINSCOPE('ProductSubcategory'[ProductSubcategory]), FORMAT((Prodeje/1000), "#,##0.00 tis. Kč", "cs-cz"),
        ISINSCOPE(ProductCategory[ProductCategory]), FORMAT((Prodeje/1000000), "#,##0.00 mil. Kč", "cs-cz"),
        FORMAT((Prodeje/1000000), "#,##0.00 mil. Kč", "cs-cz")
    )
VAR Vysledek =
    IF
    (
        NOT ISBLANK(Prodeje),
        Vypocet
    )
RETURN
    Vysledek

Ve výše uvedeném výpočtu si do první proměnné ukládáme hodnotu měřítka [Prodeje], protože tato hodnota bude v následující části výpočtu několikrát použita ve stejném kontextu.

Následuje samotná funkce SWITCH(), ve které je v prvním argumentu uvedena funkce TRUE(), která pouze vrací hodnotu TRUE. Tímto v podstatě říkáme, že chceme vrátit první hodnotu, pro kterou bude platit, že definovaná podmínka v seznamu hodnot ve druhém a dalších argumentech funkce SWITCH() vrací hodnotu TRUE. V seznamu hodnot pak ověřujeme v jaké úrovni hierarchie  se nacházíme, a to pomocí funkce ISINSCOPE(). Výsledná hodnota pak bude jiná pro každou úroveň hierarchie, protože v každé úrovni používáme jinou definici výsledku ve funkci FORMAT().

I v tomto případě záleží na pořadí, v jakém podmínky vyhodnocujeme. Pokud bychom ve funkci SWITCH() začali například úrovní 'ProductCategory[ProductCategory], výsledek by byl pro všechny úrovně stejný - hodnoty v mil. Kč. Důvodem je fakt, že pokud jsme například v řádku konkrétního produktu, tak je splněna i podmínka, kterou vyhodnocujeme pro úroveň nadřazenou. Jinak řečeno, pokud se nacházíme v úrovni produktu, tak platí, že jsme také v dosahu všech nadřazených úrovní, do kterých je konkrétní produkt zařazen, to znamená že jsme na úrovni produktu v dosahu jedné konkrétní kategorie nebo podkategorie. Pořadí vyhodnocení podmínek je tedy důležité pro dosažení požadované funkčnosti. V těchto typech výpočtů začínáme při ověřování aktuální úrovně v hierarchii ve většině situací vždy od nejnižší úrovně.

Měřítko [Prodeje (formát podle aktuální úrovně)] má jeden velký nedostatek, který spočívá v tom že funkce FORMAT() vrací hodnoty ve formátu STRING. Měřítko [Prodeje (formát podle aktuální úrovně)] proto nemůžeme používat například v grafech ve kterých jsou jednotlivé body vykresleny podle hodnoty měřítka, což přirozeně není možné v případě, kdy je výsledná hodnota měřítka textový řetězec. Tento nedostatek můžeme obejít například pomocí Dynamického formátu měřítka.

Funkce SWITCH a Dynamický formát měřítka

V definici Dynamického formátu měřítka můžeme používat všechny DAX funkce jako v kterémkoliv jiném výpočtu, včetně funkce SWITCH() nebo FORMAT().  Na rozdíl od měřítka [Prodeje (formát podle aktuální úrovně)] ale při použití Dynamického formátu nebudeme pro vykreslení jednotlivých bodů ve vizuálech použit textový řetězec, ale originální hodnota měřítka. Začít můžeme tím že si vytvoříme kopii měřítka [Prodeje].

Měřítko:

Prodeje (dynamický formát) = [Prodeje]

Následně označíme měřítko [Prodeje (dynamický formát)], a na kartě "Nástroje měr" nastavíme formát na "Dynamicky".

DAX funkce SWITCH 6

Nyní máme vedle DAX editoru na výběr dvě možnosti, "Míra" a "Formát". Pokud vybereme možnost "Formát", můžeme definovat formát měřítka libovolným způsobem.

DAX funkce SWITCH 7

Dynamický formát měřítka je primárně určen pro definici formátu na základě zástupných symbolů, podobně jako například Vlastní formát čísla v Excelu. Pokud chceme vrátit jako výsledný formát přesnou hodnotu, musíme tuto hodnotu převést na textový řetězec, aby nedošlo k použití některých symbolů z výsledné hodnoty jako zástupných symbolů (problémy dělá především číslovka 0, což je zástupný symbol za číslo). Proto se k samotnému výsledku Dynamického formátu, pokud danou hodnotu nechceme používat jako zástupné symboly, obvykle vkládá prázdný textový řetězec vložený v uvozovkách, tedy čtyři dvojité uvozovky zřetězené se samotnou výslednou hodnotou.

Dynamický formát měřítka:

VAR Prodeje = [Prodeje]
VAR Vypocet =
    SWITCH
    (
        TRUE(),
        ISINSCOPE('Product'[ProductName]), FORMAT(Prodeje, "#,##0.00 Kč", "cs-cz"),
        ISINSCOPE('ProductSubcategory'[ProductSubcategory]), FORMAT((Prodeje/1000), "#,##0.00 tis. Kč", "cs-cz"),
        ISINSCOPE(ProductCategory[ProductCategory]), FORMAT((Prodeje/1000000), "#,##0.00 mil. Kč", "cs-cz"),
        FORMAT((Prodeje/1000000), "#,##0.00 mil. Kč", "cs-cz")
    )
RETURN
    """" & Vypocet

Pokud nyní měřítko [Prodeje (dynamický formát)] použijeme ve vizuálu Matice, výsledek bude stejný jako je výsledek měřítka [Prodeje (formát podle aktuální úrovně)], nicméně měřítko [Prodeje (dynamický formát)] můžeme bez problémů používat také v grafech.

DAX funkce SWITCH 8

Jak je možné vidět na obrázku výše, měřítka [Prodeje (dynamický formát)] a [Prodeje (formát podle aktuální úrovně)] vrací stejné výsledky.

Shrnutí

Funkce SWITCH() je důležitá funkce která výrazně zjednodušuje psaní DAX výpočtů v situacích, kdy samotná logika výpočtu vyžaduje vyhodnocení více podmínek. Oproti vnořování IF() funkcí by v těchto případech měla být funkce SWITCH() preferována, protože čitelnější a jednodušší kód je vždy méně náchylný na chyby a jednodušší při následné editaci. Při použití funkce SWITCH() si pak musíme dávat pozor zejména ve výpočtech ve kterých záleží na pořadí vyhodnocení jednotlivých argumentů, protože funkce SWITCH() vrací první výsledek pro který je splněna podmínka.

Praktické příklady, některé také s použitím funkce SWITCH(), můžete najít na stránce DAX - příklady.

Oficiální Microsoft dokumentace funkce SWITCH:
č. 13

Komentáře