DAX funkce TREATAS a vlastnost Lineage Tag

DAX funkce TREATAS() umožňuje zacházet s hodnotami v tabulce zadané v prvním argumentu jako s hodnotami ze sloupců zadaných v dalších argumentech. Použití funkce TREATAS() pak může být velmi různorodé, a to od tvorby jednoduchých filtrů až po virtuální relace mezi tabulkami.

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

V první části tohoto příspěvku si vysvětlíme pojem Lineage Tag, což je důležitá vlastnost téměř každého objektu v Tabulárním modelu, která v případě sloupců přímo souvisí s používáním funkce TREATAS(). Jakmile pochopíme jak užitečné může být mít možnost měnit v rámci DAX výpočtů Lineage Tag u jednotlivých sloupců, ať už nahraných v modelu nebo vytvořených dynamicky na základě výrazu, přejdeme k jednoduchým příkladům s použitím funkce TREATAS().

Značka původu objektu (Lineage Tag) v Tabulárním modelu

Téměř každý objekt v Tabulárním modelu má svou vlastní značku původu, kterou najdeme v metadatech modelu pod anglickým pojmem Lineage Tag. Tato značka je interním identifikátorem daného objektu. Jedinečný Lineage Tag má také každý sloupec, a právě u sloupců můžeme v rámci DAX výpočtů efektivně manipulovat s touto vlastností pomocí funkce TREATAS().

Na následujícím obrázku je zobrazena výseč z tabulky, která obsahuje tři sloupce: název tabulky nahrané v modelu, název sloupců z této tabulky a Lineage Tag každého sloupce.

DAX funkce TREATAS a vlastnost Lineage Tag 2

Samotné hodnoty ve sloupci Lineage Tag nejsou pro psaní DAX výpočtů důležité. Důležité ale je že každý sloupec má jedinečný Lineage Tag. 

Stejně jako nativní sloupce nahrané v modelu, také sloupce vytvořené v rámci DAX výpočtů mají Lineage Tag. U sloupců a tabulek, které jsou vytvořené a dostupné pouze v rámci DAX výrazu hovoříme o takzvaném anonymním původu neboli o anonymním Lineage Tagu. Ani zde není při psaní DAX výrazů důležité, jakým způsobem jsou tyto anonymní sloupce interně identifikovány. Důležité je ale opět to, že Lineage Tag sloupců vytvořených a dostupných pouze v rámci DAX výpočtů je jiný než Lineage Tag jakéhokoliv nativního sloupce nebo počítaného sloupce nahraného v modelu.

Lineage Tag a funkce TREATAS

Pokud se přesuneme zpět k funkci TREATAS(), tak pomocí této funkce můžeme změnit Lineage Tag jednoho nebo více sloupců z tabulky zadané v prvním argumentu na Lineage Tag některého ze sloupců nahraných v modelu. Díky tomu můžeme anonymní sloupce vytvořené a dostupné pouze v rámci DAX výpočtu používat jako sloupce nahrané v modelu. Stejně tak ale můžeme v rámci DAX výpočtu pomocí funkce TREATAS() změnit Lineage Tag sloupce nahraného v modelu na Lineage Tag jiného sloupce pocházejícího také z některé z tabulek nahraných v modelu.

Všechny výše uvedené informace se možná mohou zdát po prvním pohled velmi abstraktní. Na následujících jednoduchých příkladech si proto ukážeme jak přenést všechny tyto informace do praxe pomocí funkce TREATAS().

Příklady použití funkce TREATAS

Začít můžeme jednoduchým příkladem. Uvažujme například následující DAX dotaz.

DAX dotaz:

EVALUATE
{
    "Black", "Blue", "Green"
}

Výsledkem výše uvedeného DAX dotazu je anonymní tabulka s jedním sloupcem. Tento sloupec s anglickými názvy barev je dostupný pouze v době vyhodnocení DAX dotazu, a jako takový má, na rozdíl od sloupců nahraných v modelu, anonymní Lineage Tag.

DAX funkce TREATAS a vlastnost Lineage Tag 3

Anonymní tabulku vytvořenou pomocí konstruktoru tabulky (složené závorky) můžeme použít také v měřítku. Protože filtry ve funkci CALCULATE() jsou tabulky, následující definice měřítka je naprosto validní a nevrací žádnou chybu.

Měřítko:

Prodeje (Anonymní tabulka ve filtru) =
CALCULATE
(
    [Prodeje],
    {"Black", "Blue", "Green"}
)

V Power BI reportu si můžeme vytvořit nový vizuál Matice, ve kterém použijeme roky z kalendářní tabulky v řádcích a do hodnot vložíme měřítko [Prodeje] a nově vytvořené měřítko [Prodeje (Anonymní tabulka ve filtru)].

DAX funkce TREATAS a vlastnost Lineage Tag 4

Jak můžeme vidět na obrázku výše, měřítko [Prodeje] a měřítko [Prodeje (Anonymní tabulka ve filtru)] vrací stejné výsledky, a to prodeje za všechny produkty v aktuálním roce v aktuálním řádku vizuálu.

Důvodem proč měřítko [Prodeje (Anonymní tabulka ve filtru)] vrací stejné hodnoty jako měřítko [Prodeje] je, že tabulka ve filtru funkce CALCULATE() nefiltruje model, protože sloupec s barvami produktů v této anonymní tabulce má jiný Lineage Tag než kterýkoliv sloupec pocházející z modelu.

Abychom mohli použít efektivně anonymní tabulku ve filtru funkce CALCULATE(), potřebujeme ve výpočtu definovat sloupec, který pochází z některé z tabulek nahraných v modelu a který bude filtrovat měřítko [Prodeje]. Vzhledem k hodnotám uvedeným v anonymní tabulce se přirozeně bude jednat o sloupec s barvami produktů. K tomu můžeme použít právě funkci TREATAS() následujícím způsobem.

Měřítko:

Prodeje (Black, Blue, Green) =
CALCULATE
(
    [Prodeje],
    TREATAS
    (
        {"Black", "Blue", "Green"},
        'Product'[Color]
    )
)

Prvním argumentem funkce TREATAS() v měřítku uvedeném výše je anonymní tabulka s jedním sloupcem a třemi anglickými názvy barev. Tyto hodnoty pak budou použity ve filtru funkce CALCULATE() tak, jako by patřili do sloupce 'Product'[Color]. Pokud by některá z uvedených barev neexistovala ve sloupci 'Product'[Color], tato barva by byla z výsledku funkce TREATAS() vyloučena. To je případ barvy "Green". V této barvě se žádný z produktů neprodává a tato barva se proto nevyskytuje ve sloupci 'Product'[Color]. Výsledkem měřítka [Prodeje (Black, Blue, Green)] jsou tak ve skutečnosti prodeje pouze za produkty v modré a černé barvě.

DAX funkce TREATAS a vlastnost Lineage Tag 5

Tabulka zadaná v prvním argumentu funkce TREATAS() může mít libovolné množství sloupců. Ke každému sloupci z této tabulky ale musíme uvést v dalších argumentech funkce TREATAS() odpovídající sloupec z některé z tabulek nahraných v modelu.

Měřítko:

Prodeje (Modrá a černá kola) =
VAR TabulkaDoFiltru =
    {
        ("Blue", "Bikes"),
        ("Black", "Bikes")
    }
VAR Vypocet =
    CALCULATE
    (
        [Prodeje],
        TREATAS
        (
            TabulkaDoFiltru,
            'Product'[Color],
            'Product'[Category]
        )
    )
RETURN
    Vypocet

Tabulka v proměnné TabulkaDoFiltru nyní obsahuje dva sloupce, jeden sloupec s barvami a jeden sloupec s názvy kategorií produktů. Jedná se ale stále o anonymní sloupce a pokud chceme hodnoty z těchto sloupců použít jako filtry modelu, můžeme opět použít funkce TREATAS(), jak je možné vidět v proměnné Vypocet.

DAX funkce TREATAS a vlastnost Lineage Tag 6

Tabulka v prvním argumentu funkce TREATAS() může obsahovat ve sloupcích hodnoty, které následně můžeme přiřadit do sloupců pocházejících z různých tabulek v modelu.

Měřítko:

Prodeje (Modrá a černá kola v 2020) =
VAR TabulkaDoFiltru =
    {
        ("Blue", "Bikes", 2020),
        ("Black", "Bikes", 2020)
    }
VAR Vypocet =
    CALCULATE
    (
        [Prodeje],
        KEEPFILTERS
        (
            TREATAS
            (
                TabulkaDoFiltru,
                'Product'[Color],
                'Product'[Category],
                'Date'[Rok]
            )
        )
    )
RETURN
    Vypocet

V proměnné TabulkaDoFiltru je nyní tabulka se třemi sloupci. V prvním sloupci jsou barvy, ve druhém sloupci názvy kategorií a ve třetím sloupci roky. Jak je možné vidět v proměnné výpočet, ve funkci TREATAS() je možné přiřadit tyto anonymní sloupce ke sloupcům pocházejícím z různých tabulek v modelu.

DAX funkce TREATAS a vlastnost Lineage Tag 7

V měřítku [Prodeje (Modrá a černá kola v 2020)] je funkce TREATAS() obalena funkcí KEEPFILTERS(). Funkce KEEPFILTERS() je v tomto měřítku použita abychom nepřepisovali vnější filtry působící na výpočet z řádků vizuálu. Funkci KEEPFILTERS() jsme dosud v kombinaci s funkcí TREATAS() nemuseli použít, protože v řádcích vizuálu byl sloupec s roky z kalendářní tabulky, a ve filtru funkce CALCULATE() jsme dosud používali jiné sloupce. Jakmile jsme ale přidali do filtru funkce CALCULATE() také sloupec s roky z kalendářní tabulky, který je použitý také v řádcích vizuálu, funkce KEEPFILTERS() je potřebná v případě že nechceme přepsat filtry působící na výpočet z řádku vizuálu. Pokud bychom funkci KEEPFILTERS() vynechali, měřítko by vracelo pro každý rok stejnou hodnotu.

DAX funkce TREATAS a vlastnost Lineage Tag 8

Ve všech dosud uvedených příkladech jsme používali pro zjednodušení konstruktor tabulky pro vytvoření tabulky určené pro první argument funkce TREATAS(). Tímto způsobem se ale funkce TREATAS() většinou nepoužívá, vyjma generování DAX dotazů Power BI vizuály nebo jinými nástroji, protože filtry ve funkci CALCULATE() můžeme vytvořit i jednodušeji bez použití funkce TREATAS().

Nyní, když už máme představu jakým způsobem funkce TREATAS() funguje, můžeme si ukázat více praktický příklad. Funkce TREATAS() je často užitečná v situacích, kdy potřebujeme vytvořit v rámci DAX výpočtu počítaný sloupec ve virtuální, pouze v době vyhodnocení výpočtu dostupné tabulce, a tento sloupec následně použít ve filtru funkce CALCULATE(). Takto vytvořený sloupec je totiž sloupec s anonymním Lineage Tagem, a to i přes to že může obsahovat existující hodnoty z některého ze sloupců pocházejícího z tabulky nahrané v modelu.

Uvažujme například situaci, kdy bychom chtěli vidět prodeje pouze za produkty, které byly v rámci každého dne nejúspěšnější z pohledu prodejů. Algoritmus takovéhoto výpočtu pak může vypadat následovně.

V první proměnné si vytvoříme virtuální tabulku se dvěma sloupci. První sloupec bude obsahovat dny z kalendářní tabulky, druhý sloupec pak bude obsahovat identifikátor produktu, který byl v daném dnu nejlepší z pohledu prodejů. Tuto tabulku se dny a nejlepšími produkty v daný den pak použijeme ve filtru funkce CALCULATE(). Protože má ale sloupec s nejlepšími produkty pro každý den anonymní Lineage Tag, použijeme funkci TREATAS() pro přiřazení nového Lineage Tagu z existujícího sloupce z tabulky nahrané v modelu. Celý takto popsaný výpočet může vypadat například následovně.

Měřítko:

Prodeje nejlepších produktů dne =
VAR DnyANejlepsiProdukty =
    ADDCOLUMNS
    (
        VALUES(Sales[Order Date]),
        "@Nejlepší produkt",
        TOPN
        (
            1,
            CALCULATETABLE(VALUES('Sales'[ProductKey])),
            [Prodeje], DESC,
            Sales[ProductKey], ASC
        )
    )
VAR TabulkaDoFiltru =
    TREATAS
    (
        DnyANejlepsiProdukty,
        'Date'[Date],
        'Product'[ProductKey]
    )
VAR Vysledek =
    CALCULATE
    (
        [Prodeje],
        TabulkaDoFiltru
    )
RETURN
    Vysledek

Nové měřítko si můžeme vložit do původního vizuálu s roky v řádcích a zobrazit si výsledky.

DAX funkce TREATAS a vlastnost Lineage Tag 9

Měřítko [Prodeje nejlepších produktů dne] vrací sumu za prodeje pouze těch produktů, které byly v aktuální den v roce nejlepší z pohledu prodejů. Jedná se tedy pouze o výseč prodejů, v porovnání s hodnotami měřítka [Prodeje].

Shrnutí

Používání funkce TREATAS() je relativně abstraktní. Funkce TREATAS() totiž vrací na první pohled stejnou tabulku, jakou zadáme v prvním argumentu této funkce. Rozdíl mezi zadanou tabulkou a tabulkou vrácenou je pak pouze v tom, jaký vztah mají hodnoty v jednotlivých sloupcích ke sloupcům nahraným v modelu. Ve filtrech funkce CALCULATE() totiž můžeme efektivně používat pouze ty sloupce, které jsou součástí modelu, a nikoliv sloupce s anonymním Lineage Tagem.

Funkci TREATAS() ale můžeme používat také pro změnu Lineage Tagů z jednoho nebo více existujících sloupců modelu na jiné existující sloupce v modelu. V takovémto případě mluvíme o takzvaných virtuální relacích mezi tabulkami. Používání virtuálních relací je ale relativně komplexní téma které si zaslouží samostatný příspěvek.

Oficiální dokumentace funkce TREATAS:
https://learn.microsoft.com/cs-cz/dax/treatas-function

Stáhnout soubor s řešením.
č. 95

Komentáře