Oblasti použití jazyka DAX
Co se naučíte
- Počítané sloupce: RELATED(), LOOKUPVALUE(), kdy je používat vs Power Query
- Měřítka: Agregace v kontextu filtru, base vs compound measures
- Počítané tabulky: CALENDAR(), SUMMARIZE(), DISTINCT()
- Visual Calculations (nové v 2024): Když měřítka nestačí
- Rozhodování: Sloupec nebo míra? Tabulka nebo query?
Počítané sloupce (Calculated Columns)
Počítaný sloupec se vyhodnocuje řádek po řádku a uloží se v modelu. Je součástí tabulky jako normální sloupec.
Základní syntax a Use cases — reálné příklady z AdventureWorks
-- Případ 1: Aritmetický výpočet z hodnot řádku -- FactInternetSales[Margin detail] FactInternetSales[SalesAmount] - FactInternetSales[TotalProductCost] -- Případ 2: Concatenace — složený klíč pro párování -- FactInternetSales[record_key] FactInternetSales[CurrencyKey] & "_" & FactInternetSales[OrderDateKey] -- Případ 3: RELATED — přes přímou relaci -- DimProduct[Sorter] — Sorter z tabulky Category Group RELATED('Category Group'[Sort]) -- Případ 4: RELATED + VAR + podmínka -- DimProduct[Category] VAR _rel = RELATED(DimProductCategory[EnglishProductCategoryName]) RETURN IF(_rel = BLANK(), "Other", _rel)
-- Případ 5: LOOKUPVALUE bez přímé relace (1 kritérium) -- DimProduct[Subcategory] LOOKUPVALUE( DimProductSubcategory[EnglishProductSubcategoryName] -- co chci vrátit ,DimProductSubcategory[ProductSubcategoryKey] -- skenovaný sloupec ,DimProduct[ProductSubcategoryKey] -- hledaná hodnota pro shodu ) -- Případ 6: LOOKUPVALUE se dvěma kritérii (kurz měny + datum) -- FactInternetSales[Sales Original] LOOKUPVALUE( FactCurrencyRate[EndOfDayRate] -- co hledám ,FactCurrencyRate[Date] -- skenovaný sloupec 1 ,FactInternetSales[OrderDate] -- hledaná hodnota 1 ,FactCurrencyRate[CurrencyKey] -- skenovaný sloupec 2 ,FactInternetSales[CurrencyKey] -- hledaná hodnota 2 ) * FactInternetSales[SalesAmount]
RELATED() vs LOOKUPVALUE()
| Funkce | Kdy se používá | Výhody | Omezení |
|---|---|---|---|
| RELATED() | Existuje přímá relace 1:N | Jednoduché, snadný audit relací | Potřebuje relaci; řešení méně flexibilní |
| LOOKUPVALUE() | Složité lookup bez přímé relace | Flexibilní, může mít více kritérií | Pomalejší, méně čitelné |
Kdy použít Calculated Column vs Power Query
| Scenario | Calculated Column | Power Query |
|---|---|---|
| Transformace jednoho sloupce | ✓ Rychlejší vývoj | ✓ Snižuje model size |
| Kategorizace, bucket | ✓ Dynamické se filtr contextom | ✓ Předvypočítáno, bez refresh nutnosti |
| Lookup z jiné tabulky | ✓ Jednoduché, ale paměť-náročné | ✓ Merge, lepší pro velké sady |
Měřítka (Measures)
Míra je vyhodnocena v kontextu filtru (slicing/dicing) a nevede se do modelu. Optimální pro agregace.
Base Measures — reálné míry z kurzu
Základní míra (base measure) provádí jednoduchou agregaci a slouží jako stavební blok pro složitější výpočty.
-- Internet prodeje (internetový kanál) # Internet = SUM(FactInternetSales[SalesAmount]) -- Reseller prodeje (distribuční kanál) # Reseller = SUM(FactResellerSales[SalesAmount])
Compound Measures — složené míry s podmíněnou logikou
-- Cíl (Target): BLANK na úrovni měsíce, jinak suma -- HASONEVALUE = TRUE, pokud je vybrán právě jeden měsíc # TGT = IF( HASONEVALUE('DimDate'[MonthNumberOfYear]) ,BLANK() ,SUM('FactSalesQuota'[SalesAmountQuota]) ) -- Variance vs Target: BLANK pokud chybí TGT nebo Reseller # VTGT = IF( ISBLANK([# TGT]) || ISBLANK([# Reseller]) , BLANK() , [# Reseller] - [# TGT] ) -- Splnění plánu v %: DIVIDE pro bezpečné dělení % TGT = DIVIDE( [# Reseller] ,[# TGT] )
# pro absolutní hodnoty a % pro procenta. To pomáhá seskupovat míry a usnadňuje orientaci v Field Listu.Implicit vs Explicit Measures
Implicit (Default): Power BI automaticky vytvoří agregaci (SUM, AVERAGE, ...) když přetáhnete sloupec do measure placeholde.
Explicit (Doporučeno): Vy explicitně definujete míru v Field listu. Lépe se audituje a řídí.
Počítané tabulky (Calculated Tables)
Počítaná tabulka je tabulka vytvořená pomocí DAX výrazu a uložená v modelu. Existují dvě hlavní použití: data a reference.
CALENDAR() pro date tabulku — reálný příklad z kurzu
Tabulka Kalendar v kurzu je vytvořena jako calculated table s dynamickým rozsahem 4 let a pak rozšířena o počítané sloupce.
-- Základ tabulky: 4 roky dynamicky od dnešního roku -- Tabulka Kalendar VAR _cy = YEAR(TODAY()) VAR _ly = _cy - 1 RETURN CALENDAR( DATE(_cy-2, 1, 1) ,DATE(_cy+1, 12, 31) )
Počítané sloupce v date tabulce
-- Rok, Kvartál, Měsíc Rok = YEAR('Kalendar'[Date]) Kvartal = QUARTER('Kalendar'[Date]) Mesic = MONTH('Kalendar'[Date]) -- Lokalizovaný název měsíce (česky) 'Mesic nazev' = FORMAT('Kalendar'[Date], "MMMM", "cs-cz") -- Příznak víkendu: WEEKDAY(...,2) vrací 1=Po...7=Ne 'Je Vikend' = WEEKDAY('Kalendar'[Date], 2) > 5 -- Integer klíč pro snapshot / párování: YYYYMMDD 'Datum Int' = 'Kalendar'[Rok] * 10000 + 'Kalendar'[Mesic] * 100 + DAY('Kalendar'[Date]) -- Relativní rok vůči dnešku (0 = letos, -1 = loni) 'Relativni rok' = DATEDIFF(TODAY(), 'Kalendar'[Date], YEAR) -- Státní svátek: LOOKUPVALUE ze samostatné tabulky svatky -- Vrátí název svátku, pokud datum v Kalendar odpovídá datu v tabulce svatky Svatek = NOT(ISBLANK( LOOKUPVALUE( 'svatky'[Svatek] -- co vrátit: název svátku ,'svatky'[Date] -- skenovaný sloupec: datum v tabulce svatky ,'Kalendar'[Date] -- hledaná hodnota: datum z Kalendar ) ))
SUMMARIZE() + ADDCOLUMNS() pro referenční tabulky
-- DOPORUČENÝ vzor: ADDCOLUMNS + SUMMARIZE (ne výpočty přímo v SUMMARIZE) -- Agregace přímo v SUMMARIZE() jsou anti-pattern — mohou vrátit nesprávné výsledky TABLE ProductSummary = ADDCOLUMNS( SUMMARIZE( Sales, Product[ProductKey], Product[ProductName], Product[Category] ), "TotalSales", SUM(Sales[Amount]) -- výpočet mimo SUMMARIZE ) -- DISTINCT: unique hodnoty jednoho sloupce TABLE UniqueCities = DISTINCT(Customer[City])
Jiné operace s tabulkami
| Funkce | Popis | Příklad |
|---|---|---|
| UNION() | Kombinuj řádky dvou tabulek | UNION(Table1, Table2) |
| EXCEPT() | Řádky z Table1 mimo Table2 | EXCEPT(Table1, Table2) |
| INTERSECT() | Běžné řádky obou tabulek | INTERSECT(Table1, Table2) |
| CROSSJOIN() | Kartézský součin | CROSSJOIN(Table1, Table2) |
Visual Calculations NEW 2024
Visual Calculations se vyhodnocují uvnitř vizuálu, nikoliv v modelu. Vidí data tak, jak jsou uspořádána na ose X nebo v řádcích matice — bez nutnosti CALCULATE, EARLIER ani složitého filter contextu.
Přehled nejdůležitějších funkcí
| Funkce | Popis | Typické použití |
|---|---|---|
| PREVIOUS() | Hodnota předchozího řádku | Srovnání inventáře den/den |
| NEXT() | Hodnota následujícího řádku | Forecast vs actual |
| RUNNINGSUM() | Kumulativní součet | YTD bez DATESYTD |
| MOVINGAVERAGE(N) | Klouzavý průměr N řádků | Vyhlazení trendu |
| RANK() | Pořadí v rámci vizuálu | Top N produkty |
| INDEX(N) | N-tý řádek (absolutní) | Benchmark: první měsíc = 100 % |
Reálný příklad z kurzu — inventář den po dni
Tabulka zobrazuje stav skladu (# Inventory Balance USD) po dnech. Visual Calculations přidávají srovnání s předchozím dnem a barevný indikátor — bez jediné změny v modelu:
-- "Versus previous": Denní změna hodnoty inventáře -- Definuje se přímo v tabulkovém vizuálu (ne v modelu!) IF(ISBLANK(PREVIOUS([# Inventory Balance USD])), BLANK(), [# Inventory Balance USD] - PREVIOUS([# Inventory Balance USD]) ) -- "Barva": Podmíněné formátování přes odvozenou Visual Calculation -- Sloupec Barva je hidden, použit jen jako podmínka formátu IF([Versus previous] < 0, "Red", "Green")
# Balance vs Previous by vyžadovala CALCULATE + DATEADD + FILTER na FactProductInventory — a stále by nevěděla, co je "předchozí řádek" v tabulce. PREVIOUS() to ví vždy, protože pracuje nad výsledkem vizuálu.Další příklady — prodeje po měsících
-- Kumulativní Internet prodeje (YTD bez DATESYTD) RUNNINGSUM([# Internet]) -- MoM Growth % — měsíc/měsíc DIVIDE( [# Internet] - PREVIOUS([# Internet]), PREVIOUS([# Internet]) ) -- Rank produktů podle # Internet (sestupně) RANK(DENSE, [# Internet], DESC) -- Klouzavý průměr 3 měsíce MOVINGAVERAGE([# Internet], 3)
Porovnání: Sloupec vs Míra vs Tabulka
| Vlastnost | Calculated Column | Measure | Calculated Table |
|---|---|---|---|
| Vyhodnocení | Řádek po řádku (row context) | V kontextu filtru (filter context) | Při refresh modelu |
| Uložení v modelu | Ano, zvětšuje model | Ne, dynamic | Ano, zvětšuje model |
| Kdy se počítá | Při refresh modelu | Na požádání (ad-hoc) | Při refresh modelu |
| Použití v sliceru | Ano, jako normální sloupec | Ne (není sloupec) | Ano, jako normální tabulka |
| Výkon | Velmi rychlé (precomputed) | Závisí na query, optimální pro web | Závisí na complexity (refresh speed) |
| Případ použití | Transformace, kategorizace, lookup | Agregace, poměry, YoY growth | Date tabulka, reference lookup |