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ů
GOC6441 · Kapitola 1

Opakování klíčových konceptů

Opakovací průběh pro pokročilé uživatele DAXu — relace, kontexty a nejčastější úskalí
⏱ 45 minut

Cíle kapitoly

  • Upevnit porozumění reláciím a jejich vlivu na filtrování v DAXu
  • Znát rozdíly mezi počítaným sloupcem, measure a počítanou tabulkou
  • Pochopit kontexty výpočtu — row context vs. filter context
  • Identifikovat a řešit časté chyby z GOC644
  • Osvěžit znalost Visual Calculations
1.1

Relace a jejich vliv na filtrování

V Power BI jsou relace základem pro automatické filtrování v DAXu. Když je relace aktivní, filtr se automaticky šíří od strany 1 (One) na stranu N (Many). Tento mechanismus ovlivňuje chování RELATED() a FILTER() funkcí.

Jednosměrné a dvousměrné relace

Ve výchozím nastavení jsou relace jednosměrné (One→Many). Výsledkem je, že:

  • Filtr ze strany One šíří se na Many: Když je vybrán konkrétní produkt, automaticky se filtrují tržby v tabulce FactInternetSales.
  • Opačný směr vyžaduje ruční řešení: Filtrování z Many na One zajistí obousměrná relace, CROSSFILTER() v rámci CALCULATE, nebo TREATAS(VALUES(Fact[Key]), Dim[Key]). Pozor: ALL() filtry odstraňuje — pro propagaci filtru v opačném směru neslouží.
ℹ
Dvousměrné relace se používají zřídka (mohou vést k výkonovým problémům) a obvykle se doporučují pouze u specifických scénářů jako je filtrování v obou směrech bez rizika.

Praktický příklad: Vliv relace na RELATED()

DAX
-- RELATED() přistupuje k hodnotám z nadřazené (One) tabulky v row contextu
TržbyNadStandardníCenu := SUMX (
  FactInternetSales,
  FactInternetSales[SalesAmount] - RELATED ( DimProduct[StandardCost] )
)

-- RELATED() funguje pouze přes aktivní relace!
-- Pokud aktivní relace neexistuje, RELATED() vrátí CHYBU (ne BLANK)
-- BLANK vrátí pouze tehdy, když relace existuje, ale pro daný řádek
-- neexistuje odpovídající záznam v nadřazené tabulce
-- Pozor: RELATED(DimProduct[ProductName]) vrací TEXT — nelze násobit číslem
Praktická cvičení: Relace▼
1
Otevřete svůj model nebo AdventureWorks DW 2019

Ověřte, že existují relace mezi FactInternetSales a DimProduct, DimDate, DimCustomer.

2
Vytvořte measure:

Tržby Prodejce = SUMX(FactResellerSales, FactResellerSales[SalesAmount])

Pak vytvořte druhou: Prodejce Jméno = RELATED(DimSalesTerritory[SalesTerritoryCountry])

Pozorujte, jak se filtrování chová v prostoru sloupce Salesperson.

1.2

Počítaný sloupec vs. Measure vs. Počítaná tabulka

Tři různé přístupy k vytváření hodnot v Power BI mají klíčové rozdíly v kontextu vyhodnocení, výkonu a využití.

Typ Kontext Kdy použít Výkon Příklad
Počítaný sloupec Row context Hodnoty, které se mění po řádcích; kategorie Vyšší paměť (uloženo v modelu) Profit = Sales - Cost
Measure Filter context Agregace; dynamické výpočty; náchylné na filtr Nižší paměť (vypočítáno na dotaz) Total Sales = SUM(Sales)
Počítaná tabulka Obojí Kalkulované tabulky pro lookup; agregace na řádcích Vyšší (tabulka uložena) TopProducts = TOPN(10, ...)

Klíčová pravidla

  • Počítaný sloupec se vyhodnocuje v row contextu — každý řádek je zpracován jednotlivě. Paměť roste s počtem řádků.
  • Measure se vyhodnocuje v filter contextu — reaguje na filtr v tabulce. Vypočítá se až při dotazu.
  • Počítaná tabulka je uložená tabulka (jako fyzická tabulka, ale dynamická). Dobrá pro reference, špatná pro paměť.
⚠
Chyba: Velké počítané sloupce (např. CALCULATE v row contextu) zvyšují paměť modelu exponenciálně. Pokud máte tabulku se 10 milióny řádků a počítaný sloupec, model bude obrovský.
1.3

Visual Calculations — připomenutí

Visual Calculations jsou nová funkce (public preview od března 2024, Power BI Desktop March 2024) umožňující výpočty na úrovni vizualizace, nezávisle na datovém modelu.

Klíčové vlastnosti

  • Provádějí se na visuálu, nikoli v datovém modelu (rychlejší, bez paměťové zátěže)
  • Pracují s ALLSELECTED() kontextem — mají přístup k datům viditelným ve vizualizaci
  • Podtrhují řádky, sloupce, relativní pozice
  • Nativně podporují procenta, pořadí, kumulativní součty
DAX — Visual Calculation: Running Total
-- Kumulativní součet (Running Total) ve Visual Calculations:
RUNNINGSUM ( [Total Sales] )

-- Nebo přes WINDOW (explicitní varianta pro složitější řazení):
CALCULATE (
  [Total Sales],
  WINDOW ( 1, ABS, 0, REL, ROWS )
)
ℹ️
ISINSCOPE ≠ Running Total. Vzor CALCULATE([Total Sales], ISINSCOPE(DimDate[MonthYear])) je conditional visibility — vypočítá míru jen pokud je MonthYear v scope vizualizace. Kumulativní součet vyžaduje RUNNINGSUM() nebo WINDOW().
✓
Visual Calculations jsou ideální pro scénáře, kde potřebujete ranking, procenta z součtu řady nebo kumulativní hodnoty bez vytváření fyzických sloupců.
1.4

Row Context vs. Filter Context — hluboké porozumění

Row Context (Kontekt řádku)

Vyskytuje se, když DAX procházení řádky tabulky jednotlivě. Zpravidla v iterátorech (SUMX, FILTERX, atd.) nebo počítaných sloupcích.

  • Máte přístup k jednotlivým hodnotám sloupců řádku
  • RELATED() pracuje přes relace
  • SUM() pracuje v aktuálním filter contextu — nevytváří ho. Context transition nastane pouze při volání míry nebo explicitním CALCULATE() uvnitř iterátoru.

Filter Context (Kontext filtru)

Toto je "prostředí" okolo measure — jaké filtry byly aplikovány z vizualizace, segmentů, apod.

  • Určuje, které řádky jsou v rozsahu measure
  • CALCULATE() ho ovlivňuje — přidává/odebírá filtry
  • Šíří se přes relace (jednosměrně)

Praktická rozdílu — Příklad

DAX
TržbyBezFiltrů := SUM ( FactInternetSales[SalesAmount] )
{-- Ovlivněno filter context (filtr z vizualizace) --}

TržbyVšechny := CALCULATE (
  SUM ( FactInternetSales[SalesAmount] ),
  ALL ( DimProduct )
)
{-- Odstraňuje filter na DimProduct, ale zachovává ostatní filtry --}

Počítaný sloupec se row contextem

Máte tabulku FactInternetSales. Vytvoříte počítaný sloupec:

DAX
ProfitMargin = DIVIDE(
  RELATED(DimProduct[StandardCost]),
  [SalesAmount]
)

Zde je row context — pro každý řádek se vypočítá marže. RELATED() funguje, protože máme v row contextu přístup k ProductKey.

Measure se filter contextem

DAX
TržbyPoProduktové kategorii = SUM(FactInternetSales[SalesAmount])

Když tuto measure vložíte do vizualizace filtrované na kategorii "Bikes", filter context se automaticky aplikuje — measure vrátí jen tržby z Bikes.

Kombinace: SUMX s RELATED a CALCULATE

DAX
TržbyZStandardnímiNáklady := SUMX (
  FILTER ( FactInternetSales, [SalesAmount] > 100 ),
  [SalesAmount] + RELATED ( DimProduct[StandardCost] )
)

SUMX vytváří row context (procházíme řádky), FILTER pracuje s filter context (filtruje podle aktuálního contextu), a RELATED přistupuje k třídě přes relaci.

1.5

Časté chyby z GOC644 a jejich řešení

Chyba 1: Zapomenutí na ALL() nebo VALUES()▼

Problém: Measure výsledky neodpovídají očekávání, protože filter context není správně smazán.

DAX (Špatně)
PercentoZCelkuŠpatně := DIVIDE (
  [Tržby],
  SUM ( FactInternetSales[SalesAmount] )
)
{-- Jmenovatel má stejný filter context jako čitatel!
    Vždycky vrátí 1.0 (nebo BLANK). --}
DAX (Správně)
PercentoZCeluSpráv := DIVIDE (
  [Tržby],
  CALCULATE (
    SUM ( FactInternetSales[SalesAmount] ),
    ALL ( DimProduct )
  )
)
{-- ALL() odstraní filter na DimProduct z filter contextu --}
Chyba 2: SUMX namíste SUM v agregacích▼

Problém: Pomalá measure, protože se iteruje bez nutnosti.

DAX (Pomalé)
TržbyPomalé := SUMX (
  FactInternetSales,
  FactInternetSales[SalesAmount]
)
{-- Zbytečná iterace! --}
DAX (Rychlé)
TržbyRychlé := SUM ( FactInternetSales[SalesAmount] )
{-- Storage Engine si poradí, je to rychlejší --}
Chyba 3: Míra v predikátu FILTER() — zbytečný Formula Engine▼

Problém: FILTER() s mírou v predikátu způsobuje, že se každý řádek vyhodnocuje ve Formula Engine (pomalé). Filtr se sloupcem je naopak správný vzor — Storage Engine si s ním poradí přímo.

DAX (✓ Správně — sloupec v predikátu)
Tržby10Plus := SUMX (
  FILTER ( FactInternetSales, FactInternetSales[OrderQuantity] > 10 ),
  FactInternetSales[SalesAmount]
)
-- Sloupec v predikátu = Storage Engine filtr = rychlé
DAX (✗ Pomalé — míra v predikátu FILTER)
TržbyPomaleFiltr := SUMX (
  FILTER ( FactInternetSales, [OrderQtyMeasure] > 10 ),
  FactInternetSales[SalesAmount]
)
-- Míra v predikátu = Formula Engine pro každý řádek = pomalé
-- Preferujte CALCULATE([TržbyMíra], FactInternetSales[OrderQuantity] > 10)

Řešení: V predikátu FILTER() používejte sloupce (rychlé, SE pushdown). Pokud filtrujete podle míry, zvažte CALCULATE s podmínkou na sloupci.

💡
Zlaté pravidlo: Pokud máte problém s výsledkem measure, nejdříve si ujasněte, jaký filter context právě platí, a pak rozhodněte, zda ho potřebujete měnit pomocí CALCULATE().
1.6

Interaktivní shrnutí a kvíz

Která z těchto measures vrátí procento z celkového součtu bez ohledu na filtr?

Odpověď: Measure s CALCULATE(..., ALL(...)), která odstraní filtr v jmenovateli.

DAX
DIVIDE([Tržby], CALCULATE([Tržby], ALL(DimProduct)))

Jaký je rozdíl mezi SUMX a SUM v jednoduchém scénáři?

Odpověď: SUM je optimalizovaný Storage Engine, SUMX je iterátor. Pro jednoduchou agregaci bez logiky je SUM vždycky rychlejší.

Kdy SUMX? Když potřebujete logiku v každém řádku (RELATED, DIVIDE, podmínky).

Co je Visual Calculation a kdy se hodí?

Odpověď: Je to výpočet na úrovni vizualizace (ne v modelu). Hodí se pro ranking, running totals, procenta řady — bez paměťové zátěže modelu.

✓
Připraveni? Pokud jste porozuměli relacím, kontextům a výběru správného typu objektu (sloupec/measure/tabulka), jste připraveni pro pokročilé techniky v dalších kapitolách!