Tržby v rámci životního cyklu výrobku v Power BI a DAX

Tržby v rámci životního cyklu výrobku v Power BI a DAX

Tento příspěvek obsahuje výpočet tržeb v různých časových úsecích v průběhu celého prodejního cyklu výrobku s tím, že u každého výrobku může toto období začínat v jiný den, v závislosti na tom, kdy se každý jeden produkt začal prodávat. Díky tomu můžeme spravedlivě porovnávat výkonnost jednotlivých výrobků v různých fázích životního cyklu, protože při porovnání budeme u každého výrobku pracovat se stejně dlouhými časovými úseky, které ale mohou začínat v jiné dny, vždy s ohledem na to kdy se daný produkt začal prodávat.

Cílem příkladu tedy není následovat teorii životního cyklu výrobku tak, jak je popsána z pohledu Ekonomie, kde je životní cyklus rozdělen typicky na čtyři fáze (Zavádění produktu, Růst zájmu o produkt, Kulminace zájmu a zralost produktu, Útlum zájmu o produkt) a každá fáze životního cyklu výrobku má různou dobu trvání. V tomto příspěvku budeme pracovat s pevně danými časovými úseky, které budou v součtu pokrývat celé období, ve kterém se produkty prodávaly.

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

Všechny výpočty jsou vytvořeny ve cvičném Power BI 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.

Začátek životního cyklu výrobku

Firma Adventure Works se zabývá prodejem jízdních kol a dalšího cyklistického vybavení. Prodávané produkty jsou z velké části módní záležitostí a prodej jednoho produktu trvá vždy pouze něco málo přes jeden rok.

Pokud ale vložíme do Power BI vizuálu Matice do řádků produkty, do sloupců roky a měřítko [Prodeje] do hodnot, na první pohled se může zdát, že produkty se prodávají obvykle dva roky.

Tržby v rámci životního cyklu výrobku v Power BI a DAX 2

K prodeji jednotlivých produktů sice dochází ve většině případů ve dvou kalendářních letech, nicméně v každém roce se daný produkt prodává pouze v určitých měsících. Obecně můžeme říct, že se často jedná o prodeje ve druhém pololetí prvního roku a v prvním pololetí následujícího roku. Každý produkt se také může začít prodávat v jiný den. Proto není možné jednoduše vložit atribut z kalendářní tabulky na osu vizuálu a porovnávat produkty mezi sebou. Takovéto porovnání, řekněme například na úrovni měsíců, by mohlo být nespravedlivé v případě, kdy se jeden porovnávaný produkt začal prodávat na začátku měsíce a druhý porovnávaný produkt až v druhé polovině stejného měsíce.

Tržby v rámci životního cyklu výrobku v Power BI a DAX 3

Při pohledu na obrázek výše je zřejmé, že každý produkt se může začít prodávat v jiný den, a není proto příliš spravedlivé porovnávat prodeje produktů v rámci období, jehož začátek a konec je pevně stanoven kalendářem.

Při porovnání produktů proto budeme vycházet u každého produktu z data, ve kterém došlo k prvnímu prodeji produktu. Následně můžeme přičíst k tomuto datu určité období, uvažujme například čtyři měsíce (vzhledem k celkové délce životního cyklu produktů v použitém modelu), a toto období použít jako filtr u každého produktu. Na základě takto popsaného výpočtu budeme schopni určit, jaké tržby vygeneroval každý produkt v prvních čtyřech měsících jeho prodejů, v měsících 5 až 8, v měsících 9 až 12, atd.

Tržby v prvním období prodeje produktu

Jako první období budeme uvažovat první čtyři měsíce, ve kterých se daný produkt prodával. U každého produktu tedy nejdříve najdeme první den s prodeji, a jako filtr použijeme období mezi prvním dnem s prodeji a stejným dnem, ke kterému přičteme čtyři měsíce.

Tržby v rámci životního cyklu výrobku v Power BI a DAX 4

První verze měřítka, které bude vracet prodeje za první čtyři měsíce u každého produktu, může vypadat následovně.

Měřítko:

Prodeje (měsíce 1-4) - jednoduché =
VAR PrvniDenProdeje =
    CALCULATE
    (
        MIN(Sales[Order Date]),
        ALLEXCEPT(Sales, 'Product'[Produkt a ID])
    )
VAR Vypocet =
    IF
    (
        HASONEVALUE('Product'[Produkt a ID]),
        CALCULATE
        (
            [Prodeje],
            DATESINPERIOD('Date'[Date], PrvniDenProdeje, 4, MONTH)
        )
    )
RETURN
    Vypocet

Nové měřítko bude vracet sumu za prodané produkty v prvních čtyřech měsících od uvedení každého produktu na trh.

Tržby v rámci životního cyklu výrobku v Power BI a DAX 5

Problémem takto vytvořeného měřítka je, že nebude vůbec reagovat na filtry z datumové tabulky. Z logiky výpočtu je zřejmé, že musíme přepisovat filtry z datumové tabulky, protože pro každý produkt chceme zobrazit prodeje za čtyři měsíce, ale u každého produktu může jít o jiné čtyři měsíce z pohledu kalendářní tabulky, protože každý produkt se mohl začít prodávat v jiný den.

Přesto se může stát, že uživatel bude chtít vidět pouze produkty, které se začaly prodávat v jím vybraném období. Z pohledu jazyka DAX tedy můžeme doplnit podmínku, která bude ověřovat, zda se aktuální produkt začal prodávat v období vybraném například v průřezu.

Měřítko:

Prodeje (měsíce 1-4) =
VAR PrvniDenProdeje = CALCULATE(MIN(Sales[Order Date]), ALLEXCEPT(Sales, 'Product'[Produkt a ID]))
VAR PrvniDenProdejeVAktualnimObdobi = MIN(Sales[Order Date])
VAR VybranyJedenProdukt = HASONEVALUE('Product'[Produkt a ID])
VAR Vypocet =
    IF
    (
        VybranyJedenProdukt &&
        PrvniDenProdeje = PrvniDenProdejeVAktualnimObdobi,
        CALCULATE
        (
            [Prodeje],
            DATESINPERIOD('Date'[Date], PrvniDenProdeje, 4, MONTH)
        )
    )
RETURN
    Vypocet

V takto vytvořeném měřítku se výsledek bude zobrazovat pouze v případě, kdy je první den s prodeji produktu dostupný v aktuálním kontextu vyhodnocení. Pokud tedy například uživatel vybere v průřezu pouze rok 2018, měřítko [Prodeje (měsíce 1-4)] bude vracet prodeje za první čtyři měsíce u produktů, které se začali prodávat v právě vybraném roce.

Tržby v rámci životního cyklu výrobku v Power BI a DAX 6

Podobným způsobem si můžeme doplnit měřítka pro další období, tedy pro období mezi 5 – 8 měsícem, 9 – 12 měsícem a 13 – 16 měsícem.

Tržby v dalších obdobích prodeje produktu

Jedinou změnou při výpočtu tržeb v dalších obdobích bude druhý argument funkce DATESINPERIOD(), kde datum s prvním dnem s prodeji pro každé následující období posuneme pomocí funkce EDATE() o interval, který je již zahrnut v předcházejících obdobích. Výpočet prodejů v 5 až 8 měsíci tak může vypadat následovně.

Měřítko:

Prodeje (měsíce 5-8) =
VAR PrvniDenProdeje = CALCULATE(MIN(Sales[Order Date]), ALLEXCEPT(Sales, 'Product'[Produkt a ID]))
VAR PrvniDenProdejeVAktualnimObdobi = MIN(Sales[Order Date])
VAR VybranyJedenProdukt = HASONEVALUE('Product'[Produkt a ID])
VAR Vypocet =
    IF
    (
        VybranyJedenProdukt &&
        PrvniDenProdeje = PrvniDenProdejeVAktualnimObdobi,
        CALCULATE
        (
            [Prodeje],
            DATESINPERIOD('Date'[Date], EDATE(PrvniDenProdeje, 4), 4, MONTH)
        )
    )
RETURN
    Vypocet

Výpočet pro období mezi 9 až 12 měsícem bude vypadat následovně.

Měřítko:

Prodeje (měsíce 9-12) =
VAR PrvniDenProdeje = CALCULATE(MIN(Sales[Order Date]), ALLEXCEPT(Sales, 'Product'[Produkt a ID]))
VAR PrvniDenProdejeVAktualnimObdobi = MIN(Sales[Order Date])
VAR VybranyJedenProdukt = HASONEVALUE('Product'[Produkt a ID])
VAR Vypocet =
    IF
    (
        VybranyJedenProdukt &&
        PrvniDenProdeje = PrvniDenProdejeVAktualnimObdobi,
        CALCULATE
        (
            [Prodeje],
            DATESINPERIOD('Date'[Date], EDATE(PrvniDenProdeje, 8), 4, MONTH)
        )
    )
RETURN
    Vypocet

Obdobně bude vypadat také měřítko pro období mezi 13 až 16 měsícem, opět pouze se změnou ve druhém argumentu funkce DATESINPERIOD().

Měřítko:

Prodeje (měsíce 13-16) =
VAR PrvniDenProdeje = CALCULATE(MIN(Sales[Order Date]), ALLEXCEPT(Sales, 'Product'[Produkt a ID]))
VAR PrvniDenProdejeVAktualnimObdobi = MIN(Sales[Order Date])
VAR VybranyJedenProdukt = HASONEVALUE('Product'[Produkt a ID])
VAR Vypocet =
    IF
    (
        VybranyJedenProdukt &&
        PrvniDenProdeje = PrvniDenProdejeVAktualnimObdobi,
        CALCULATE
        (
            [Prodeje],
            DATESINPERIOD('Date'[Date], EDATE(PrvniDenProdeje, 12), 4, MONTH)
        )
    )
RETURN
    Vypocet

Podobným způsobem bychom mohli přidávat další období, nebo případně upravit délku období, která je definována argumenty ve funkci DATESINPERIOD(). Pokud všechna dříve vytvořená měřítka vložíme do vizuálu Matice, výsledek bude vypadat následovně.

Tržby v rámci životního cyklu výrobku v Power BI a DAX 7

Stanovení délky a počtu období může být individuální v závislosti na požadavcích uživatelů reportu a na celkové době, po kterou se produkty prodávají. Jednoduchou úpravou výše uvedených výpočtů tak můžeme dostat například prodeje po jednotlivých týdnech, měsících nebo letech.

Všechna měřítka, která jsme si dosud vytvořili mají jeden nedostatek, který spočívá v tom že nejsou aditivní. Důvodem je že měřítka jsou vytvořena pouze za účelem vyhodnocení na úrovni jednotlivých produktů. Pokud tedy do předchozího vizuálu přidáme do řádků například kategorie produktů, tak na úrovni produktů budou měřítka vracet správné hodnoty, ale na úrovni kategorií již budou tato měřítka vracet prázdnou hodnotu BLANK. To můžeme vidět na následujícím obrázku, kde jsou ve vizuálu matice pro zjednodušení pouze tři měřítka, měřítko [Prodeje], měřítko [Prodeje (měsíce 1 - 4)] a měřítko [Prodeje (měsíce 5 - 8)].

Tržby v rámci životního cyklu výrobku v Power BI a DAX 8

Jak je možné vidět na obrázku výše, měřítka [Prodeje (měsíce 1 - 4)] a [Prodeje (měsíce 5 - 8)] nevrací v řádcích s kategoriemi produktů a v řádku souhrnů žádné hodnoty, protože v těchto řádcích není k dispozici jeden produkt, pro který bychom ve výpočtu mohli určit datum, ve který se jeden konkrétní produkt začal prodávat.

Pokud bychom chtěli zobrazovat výsledky měřítek také na vyšších úrovních než na úrovni s jednotlivými produkty, musím upravit výpočet a udělat z neaditivních měřítek měřítka aditivní, jak si ukážeme v následující části příspěvku.

Tržby v jednotlivých měsících aditivně

Způsobů, jak vytvořit výpočet s prodeji za produkty v jednotlivých obdobích prodejů tak, aby byl celý výpočet aditivní, je v jazyku DAX více. Zřejmě nejjednodušším řešením pak bude použití funkce SUMX(), ve které v prvním argumentu použijeme tabulku s jedním sloupcem, který bude obsahovat jednotlivé produkty, a v druhém argumentu funkce SUMX() použijeme podobnou logiku výpočtu, kterou jsme mohli vidět například v měřítku [Prodeje (měsíce 1 - 4)].

Měřítko:

Prodeje (měsíce 1-4) - aditivní =
SUMX
(
    VALUES('Product'[Produkt a ID]),
    CALCULATE
    (
        VAR PrvniDenProdeje = CALCULATE(MIN(Sales[Order Date]), ALLEXCEPT(Sales, 'Product'[Produkt a ID]))
        VAR PrvniDenProdejeVAktualnimObdobi = MIN(Sales[Order Date])
        VAR Vypocet =
            IF
            (
                PrvniDenProdeje = PrvniDenProdejeVAktualnimObdobi,
                CALCULATE
                (
                    [Prodeje],
                    DATESINPERIOD('Date'[Date], PrvniDenProdeje, 4, MONTH)
                )
            )
        RETURN
            Vypocet
    )
)

Za zmínku stojí vložení celého výpočtu ve druhém argumentu funkce SUMX() do funkce CALCULATE(). Funkce CALCULATE() je v tomto případě nezbytná pro změnu kontextu řádku, který je vytvořený v tabulce v prvním argumentu funkce SUMX() pro každý produkt, na kontext filtru. Díky změně kontextu řádku na kontext filtru máme jistotu že celý výpočet ve druhém argumentu funkce SUMX() bude vyhodnocen v kontextu filtru pouze jednoho produktu, a proto již také nemusíme ověřovat ve funkci IF(), zda je celý výpočet vyhodnocen v kontextu konkrétního produktu, jako tomu bylo v původní verzi výpočtu, kde jsme za tímto účelem používali funkci HASONEVALUE().

Podobným způsobem můžeme upravit také měřítka pro další období.

Měřítka:

Prodeje (měsíce 5-8) - aditivní =
SUMX
(
    VALUES('Product'[Produkt a ID]),
    CALCULATE
    (
        VAR PrvniDenProdeje = CALCULATE(MIN(Sales[Order Date]), ALLEXCEPT(Sales, 'Product'[Produkt a ID]))
        VAR PrvniDenProdejeVAktualnimObdobi = MIN(Sales[Order Date])
        VAR Vypocet =
            IF
            (
                PrvniDenProdeje = PrvniDenProdejeVAktualnimObdobi,
                CALCULATE
                (
                    [Prodeje],
                    DATESINPERIOD('Date'[Date], EDATE(PrvniDenProdeje, 4), 4, MONTH)
                )
            )
        RETURN
            Vypocet
    )
)
Prodeje (měsíce 9-12) - aditivní =
SUMX
(
    VALUES('Product'[Produkt a ID]),
    CALCULATE
    (
        VAR PrvniDenProdeje = CALCULATE(MIN(Sales[Order Date]), ALLEXCEPT(Sales, 'Product'[Produkt a ID]))
        VAR PrvniDenProdejeVAktualnimObdobi = MIN(Sales[Order Date])
        VAR Vypocet =
            IF
            (
                PrvniDenProdeje = PrvniDenProdejeVAktualnimObdobi,
                CALCULATE
                (
                    [Prodeje],
                    DATESINPERIOD('Date'[Date], EDATE(PrvniDenProdeje, 8), 4, MONTH)
                )
            )
        RETURN
            Vypocet
    )
)
Prodeje (měsíce 13-16) - aditivní =
SUMX
(
    VALUES('Product'[Produkt a ID]),
    CALCULATE
    (
        VAR PrvniDenProdeje = CALCULATE(MIN(Sales[Order Date]), ALLEXCEPT(Sales, 'Product'[Produkt a ID]))
        VAR PrvniDenProdejeVAktualnimObdobi = MIN(Sales[Order Date])
        VAR Vypocet =
            IF
            (
                PrvniDenProdeje = PrvniDenProdejeVAktualnimObdobi,
                CALCULATE
                (
                    [Prodeje],
                    DATESINPERIOD('Date'[Date], EDATE(PrvniDenProdeje, 12), 4, MONTH)
                )
            )
        RETURN
            Vypocet
    )
)

Pokud nyní vložíme do vizuálu Matice například měřítko [Prodeje (1 - 4 měsíc) - aditivní] a [Prodeje (5 - 8 měsíc) - aditivní], budou tato měřítka vracet správné výsledky také pro podkategorie produktů a v řádku souhrnů.

Tržby v rámci životního cyklu výrobku v Power BI a DAX 9

Další příklady můžete najít na stránce DAX příklady nebo na stránce Power BI. Všechny video návody jsou k dispozici na Youtubovém kanále pod tímto odkazem.

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

Komentáře