GOC644 — DAX základy (2 dny)
1. Úvod do Power BI 2. Datový model 3. Úvod do DAX 4. Oblasti použití DAX 5. Kontext výpočtu 6. Časová inteligence 7. Optimalizace DAX 8. Row Level Security 9. Nástroje
GOC6441 — Pokročilý DAX (2 dny)
1. Opakování & přehled 2. Dynamické reporty 3. DAX jako dotazovací jazyk 4. VertiPaq engine 5. Ladění výkonu 6. Composite Models 7. Workshop
Cvičení
1. Datový model 2. DAX základy 3. Kontext výpočtu 4. Časová inteligence
🏠 Rozcestník kurzů
GOC644 · Kapitola 6

Práce s časem

Time Intelligence a měření výkonu v čase — měsíc vs rok, trend analýza
⏱ 50 minut🗂 Kapitola 6

Cíle kapitoly

  • Pochopit koncept Time Intelligence v Power BI
  • Vytvořit a správně označit tabulku kalendáře
  • Ovládat funkce DATEADD, TOTALYTD
    📝
    Na blogu Jiřího Neorala: Časové kalkulace v DAX problém otevřeného období — specifický problém s otevřeným obdobím v time intelligence
    , SAMEPERIODLASTYEAR
  • Implementovat srovnání rok na rok (YoY)
  • Vytvářet running totals (YTD, QTD, MTD)
  • Vyhnout se běžným chybám
6.1

Co je Time Intelligence?

Time Intelligence (TI) je technika v Power BI/DAX, která umožňuje provádět pokročilé časové analýzy. Jde o porovnávání dat v čase, vytváření trendů a Year-over-Year analýz.

Typické případy použití

  • Year-over-Year (YoY): Srovnání prodeje letošního roku s minulým rokem
  • Year-to-Date (YTD): Součet tržeb od začátku roku po dnešek
  • Trend analýza: Vývoj prodeje v čase (týdny, měsíce)
  • Sezónnost: Analýza opakujících se vzorů v čase
  • Running totals: Kumulativní součty
ℹ️
Time Intelligence vyžaduje správně nastavenou tabulku kalendáře. To je základní požadavek pro všechny pokročilé časové funkce.

Proč ne klasický CALCULATE?

Ačkoli můžete psát Time Intelligence "ručně" pomocí CALCULATE, speciální TI funkce jsou čitelnější a méně náchylné k chybám (výkonnostně jsou na úrovni moderního DAX kompilátoru ekvivalentní):

DAX
-- Ručně (verbose, ale výkonnostně ekvivalentní):
CALCULATE(SUM(FactInternetSales[SalesAmount]),
  DimDate[Year] = MAX(DimDate[Year]) - 1
)

-- Pomocí TI funkce (čitelnější, doporučeno):
CALCULATE(SUM(FactInternetSales[SalesAmount]),
  PREVIOUSYEAR(DimDate[Date])
)
6.2

Tabulka kalendáře (Date Table)

Tabulka kalendáře je ústřední prvek Time Intelligence. Bez ní TI funkce nefungují správně nebo vůbec.

Požadavky na Date Table

  • Kontinuální data: Bez mezer mezi daty (žádné víkendy či svátky, pokud nejsou vynechány záměrně)
  • Jedinečnost: Jeden řádek na den (žádné duplikáty)
  • Označení v modelu: Musí být označena jako "Date Table" v Power BI
  • Primární klíč: Sloupec DateKey nebo FullDate bez duplikátů
  • Rozsah: Pokryje všechny data v FactTable (minimálně o rok více)

Vytvoření Date Table v Power Query

Klasický vzor v M (Power Query):

M (Power Query)
let
  MinDate = Date.From("2015-01-01"),
  MaxDate = Date.From("2024-12-31"),
  DateRange = List.Dates(MinDate, Duration.Days(MaxDate - MinDate) + 1, Duration.FromDays(1)),
  DateTable = Table.FromList(DateRange, Splitter.SplitByNothing(), {"Date"}),
  AddYear = Table.AddColumn(DateTable, "Year", each Date.Year([Date]))
in
  AddYear

Označení Date Table v Power BI

Po importu musíte tabulku označit jako Date Table:

  1. Klikněte na tabulku v modelu (v Modeling tab)
  2. Vyberte "Mark as date table
    📝
    Na blogu Jiřího Neorala: Zlo dostalo jméno Auto date/time intelligence — proč vypnout Auto date/time — důležitý antipattern
    "
  3. Zvolte správný sloupec (obvykle DateKey nebo FullDate)
⚠️
Pokud Date Table není označena, Time Intelligence funkce vrátí chybu nebo špatné výsledky. Vždy zkontrolujte označení!

Standardní sloupce v Date Table

Typicky Date Table obsahuje:

  • Date – Samotné datum (YYYY-MM-DD)
  • DateKey – Číslo jako 20231225 (YYYYMMDD)
  • Year – Rok (2023)
  • Quarter – Čtvrtletí (1, 2, 3, 4)
  • Month – Měsíc (1-12)
  • MonthName – Název měsíce (Jan, Feb...)
  • Day – Den v měsíci (1-31)
  • DayOfWeek – Den týdne (1=pondělí...7=neděle)
  • WeekNumber – Číslo týdne v roce
6.3

Základní Time Intelligence funkce

DATEADD — Posun o období

Posunuje datum o specifikovaný počet období. V kurzu používáme přesně -365 dní místo SAMEPERIODLASTYEAR, protože data přesahují roky s různým počtem dní:

DAX
-- Internet LY: prodeje stejného období před rokem (přesně -365 dní)
-- SAMEPERIODLASTYEAR je zakomentovaná varianta — obě fungují.
-- DATEADD(-365, DAY) je záměrná volba pro přesné denní srovnání v tomto modelu;
-- SAMEPERIODLASTYEAR je vhodnější pro měsíční/kvartální granularitu (mapuje celá období).
# Internet LY =
CALCULATE(
    [# Internet]
    ,--SAMEPERIODLASTYEAR('DimDate'[Date])
    DATEADD('DimDate'[Date], -365, DAY)
)

TOTALYTD — Kumulativně od začátku roku

Součet od začátku roku do aktuálního data. Reálná míra z kurzu pro Reseller kanál:

DAX
-- Reseller YTD: kumulativní součet reseller prodejů od 1.1.
# Reseller YTD =
TOTALYTD([# Reseller], 'DimDate'[Date])

TOTALMTD, TOTALQTD — Měsíc a čtvrtletí

Podobně jako TOTALYTD, ale pro měsíc nebo čtvrtletí:

DAX
Sales MTD = TOTALMTD(SUM(FactInternetSales[SalesAmount]), DimDate[Date])
Sales QTD = TOTALQTD(SUM(FactInternetSales[SalesAmount]), DimDate[Date])

SAMEPERIODLASTYEAR — Stejné období loni

Vrací data ze stejného období minulého roku. Používá se v Calculation Groups pro elegantní opakovanou aplikaci na libovolnou míru:

DAX
-- Přímé použití v míře:
Sales LY =
CALCULATE(
    [# Internet]
    ,SAMEPERIODLASTYEAR('DimDate'[Date])
)

-- V Calculation Group (viz sekce Calculation Groups níže):
-- calculationItem LY = CALCULATE(SELECTEDMEASURE(), SAMEPERIODLASTYEAR(...))

PREVIOUSYEAR, PREVIOUSMONTH — Celé období

Vrací data z minulého roku/měsíce, ale zachovává všechna data daného období:

DAX
Sales Previous Year Total =
CALCULATE(
  SUM(FactInternetSales[SalesAmount]),
  PREVIOUSYEAR(DimDate[Date])
)

DATESYTD, DATESINPERIOD — Custom periody

Vytvoří vlastní seznam dat pro Time Intelligence:

DAX
Sales Last 30 Days =
CALCULATE(
  SUM(FactInternetSales[SalesAmount]),
  DATESINPERIOD(
    DimDate[Date],
    MAX(DimDate[Date]),
    -30,
    DAY
  )
)
6.4

Year-over-Year (YoY) srovnání

YoY je jedním z nejčastějších případů použití Time Intelligence – srovnání výkonu letošního roku s minulým rokem.

Jednoduchý YoY — Aktuální vs Minulý rok

DAX
Sales Current Year = SUM(FactInternetSales[SalesAmount])

Sales Last Year =
CALCULATE(
  SUM(FactInternetSales[SalesAmount]),
  SAMEPERIODLASTYEAR(DimDate[Date])
)

YoY Growth Absolute = Sales Current Year - Sales Last Year

YoY Growth % =
DIVIDE(
  YoY Growth Absolute,
  Sales Last Year
)

YoY v kontextu měsíce

Pokud je měra použita v kontingenční tabulce s měsíci, YoY funguje automaticky:

DAX
Sales = SUM(FactInternetSales[SalesAmount])

Sales PY (Prior Year) =
CALCULATE(
  Sales,
  SAMEPERIODLASTYEAR(DimDate[Date])
)

Když vizuál filtruje na "Leden", měra se vyhodnotí pro Leden aktuálního roku a SAMEPERIODLASTYEAR vrátí Leden minulého roku.

💡
SAMEPERIODLASTYEAR je inteligentní – automaticky mapuje období (leden → leden v minulém roce, Q1 → Q1 v minulém roce).
6.5

Running Totals (YTD, QTD, MTD)

Running total (kumulativní součet) ukazuje součet od začátku období po aktuální datum.

Year-to-Date (YTD)

DAX
Revenue YTD =
TOTALYTD(
  SUM(FactInternetSales[SalesAmount]),
  DimDate[Date]
)

V kontingenční tabulce s měsíci:

  • Leden: součet Leden
  • Únor: součet Leden + Únor
  • Březen: součet Leden + Únor + Březen
  • atd.

Quarter-to-Date (QTD) a Month-to-Date (MTD)

DAX
Revenue QTD =
TOTALQTD(
  SUM(FactInternetSales[SalesAmount]),
  DimDate[Date]
)

Revenue MTD =
TOTALMTD(
  SUM(FactInternetSales[SalesAmount]),
  DimDate[Date]
)

CALCULATE + DATESYTD — alternativní YTD

TOTALYTD a CALCULATE + DATESYTD jsou ekvivalentní. Zajímavé je použít DATESYTD s jiným agregátem než SUM — například AVERAGE:

DAX
-- Internet YTD: PRŮMĚRNÁ hodnota transakce od začátku roku
-- Kombinace AVERAGE + DATESYTD — TOTALYTD by SUM nestačil
# Internet YTD =
CALCULATE(
    --[# Internet]
    --'FactInternetSales'[SalesAmount]
    AVERAGE('FactInternetSales'[SalesAmount])
    ,DATESYTD('DimDate'[Date])
)
💡
TOTALYTD vs DATESYTD: TOTALYTD je zkratka pro CALCULATE([míra], DATESYTD(...)). Pokud potřebujete jiný agregát (AVERAGE, MAX, COUNTROWS), použijte CALCULATE + DATESYTD přímo. Zakomentované řádky ukazují, jak lze v míře snadno přepínat mezi různými agregáty.
6.6

Calculation Groups — Time Calculations

Calculation Group je speciální tabulka, která aplikuje výpočet na libovolnou míru v modelu. Místo psaní zvláštních měr (# Internet LY, # Reseller LY, # Internet YTD, # Reseller YTD...) napíšete výpočet jednou a použijete ho na všechny míry.

Calculation Group Time Calculations z kurzu

DAX
-- Calculation Item: Actual — vrátí míru beze změny
SELECTEDMEASURE()

-- Calculation Item: LY — stejné období loni
CALCULATE(
    SELECTEDMEASURE()
    ,SAMEPERIODLASTYEAR('DimDate'[Date])
)

-- Calculation Item: VLY (Variance vs Last Year)
VAR _ty = SELECTEDMEASURE()
VAR _ly = CALCULATE(
    SELECTEDMEASURE()
    ,SAMEPERIODLASTYEAR('DimDate'[Date])
)
VAR _rslt =
    IF(ISBLANK(_ty) || ISBLANK(_ly), BLANK(), _ty - _ly)
RETURN _rslt

-- Calculation Item: VLY% — formatStringDefinition = "0.0%"
VAR _ty = SELECTEDMEASURE()
VAR _ly = CALCULATE(SELECTEDMEASURE(), SAMEPERIODLASTYEAR('DimDate'[Date]))
VAR _vly = IF(ISBLANK(_ty) || ISBLANK(_ly), BLANK(), _ty - _ly)
RETURN DIVIDE(_vly, _ly)
ℹ️
Jak Calculation Group funguje: Přidejte pole Time Calculations do osy nebo sloupců matice. Volba "LY" automaticky aplikuje CALCULATE + SAMEPERIODLASTYEAR na všechny míry ve vizuálu — # Internet LY, # Reseller LY i # TGT LY najednou, bez psaní samostatných měr.
6.7

Časté chyby a jak se jim vyhnout

Chyba 1: Date Table není označena

Příznaky: Time Intelligence funkce vrací chybu nebo špatné výsledky.

Řešení: Vždy označte Date Table v modelu. Jděte do Modeling > Mark as date table.

⚠️
Bez označení Date Table nebude Power BI vědět, jak funkce jako DATEADD pracovat. Toto je kritické.

Chyba 2: Mezery v datech v Date Table

Příznaky: Výsledky DATEADD nebo YoY jsou nesprávné (chybí data).

Řešení: Zajistěte, aby Date Table obsahovala všechny dny bez mezer. Pokud máte data pouze pro pracovní dny, musíte stále mít všechny dny v tabulce.

Chyba 3: Problém s filtrováním v DATEADD

Příznaky: DATEADD vrací "prázdné" výsledky.

Řešení: Ujistěte se, že Date Table má správný vztah (1:N) s faktickou tabulkou a že je aktivní.

Chyba 4: Použití DateKey (integer) místo Date sloupce

Problém: TI funkce (SAMEPERIODLASTYEAR, TOTALYTD, DATEADD apod.) vyžadují sloupec datového typu Date/DateTime. Pokud jim předáte DimDate[DateKey] (integer YYYYMMDD), výsledek bude chybný nebo míra vrátí prázdno.

DAX
-- CHYBNĚ — DateKey je integer, ne datum:
TOTALYTD(SUM(...), DimDate[DateKey])         -- ❌ nefunguje
CALCULATE(..., SAMEPERIODLASTYEAR(DimDate[DateKey]))  -- ❌ nefunguje

-- SPRÁVNĚ — Date je sloupec datového typu DateTime:
TOTALYTD(SUM(...), DimDate[Date])            -- ✓
CALCULATE(..., SAMEPERIODLASTYEAR(DimDate[Date]))   -- ✓

Řešení: Pro TI funkce vždy používejte sloupec typu Date/DateTime (v kurzu: DimDate[Date] resp. Kalendar[Date]). Sloupec DateKey (číslo) slouží jako primární klíč pro relace, ne jako argument TI funkcí.

Doporučení 5: preferujte TI funkce před ručním CALCULATE

Ruční přístup pomocí CALCULATE funguje, ale TI funkce jsou robustnější:

DAX
-- Méně robustní (funguje, ale neošetřuje edge cases automaticky):
CALCULATE(SUM(...), DimDate[Year] = YEAR(TODAY()) - 1)

-- Doporučeno — TI funkce ošetřují meziroční přechody a fiskální rok:
CALCULATE(SUM(...), PREVIOUSYEAR(...) )

Důvod: TI funkce automaticky ošetřují edge cases (meziroční přechody, přestupné roky, fiskální rok). Ruční filtr přes sloupec Year funguje pro jednoduché scénáře, ale při složitějších požadavcích se rychle zkomplikuje.

✓
Shrnutí: Vždy kontrolujte Date Table označení, zajistěte kontinuální data a používejte Time Intelligence funkce místo ručního CALCULATE.