Dokumentacja techniczna · wydanie 2.0

DAX

Katalog funkcji i wzorców obliczeniowych dla planowania w motoryzacji

Napisane dla kogoś, kto od lat planuje, budżetuje i rozlicza odchylenia w Excelu, a w DAX stawia pierwsze kroki. Każda pozycja mówi nie tylko co robi funkcja, ale jak o niej myśleć i gdzie się na niej przewrócisz. Przykłady odwołują się do jednego, spójnego modelu: sprzedaż aut, sieć dealerska, serwis, magazyn części i plan.

Pozycji w katalogu
Wzorców łączonych
12
Środowisko
Power BI · Fabric
Poziom wejścia
Od zera
00 · PRZED URUCHOMIENIEM

Sześć pojęć, bez których DAX zawsze będzie zgadywaniem

Większość „dziwnych wyników” w DAX to nie błąd składni, tylko nieporozumienie co do jednego z tych sześciu pojęć. Piętnaście minut tutaj oszczędza tydzień szukania po omacku.

01

Kolumna kontra miara

Kolumna obliczeniowa liczy się raz, przy odświeżaniu, i zapisuje wynik przy każdym wierszu — jak formuła przeciągnięta w dół arkusza. Zajmuje pamięć i nie reaguje na to, co klikniesz w raporcie.

Miara nie ma wartości, dopóki nie trafi na wizualizację. Liczy się od nowa w każdej komórce macierzy, według tego, co ta komórka aktualnie filtruje.

Zasada kciuka: jeśli wynik ma sumować się, zmieniać po kliknięciu w slicer albo pokazywać procent — to miara. Kolumna tylko wtedy, gdy potrzebujesz czegoś do grupowania, filtrowania lub osi wykresu.

02

Kontekst filtra

To zbiór wszystkich filtrów, które działają w chwili liczenia miary: wiersz i kolumna macierzy, slicery, filtry strony, legenda wykresu, klik na innym wizualu.

Miara SUM(Sprzedaz[Ilosc]) nie ma jednej wartości — w wierszu „Region Południe / marzec” zwróci coś innego niż w wierszu „Region Północ / kwiecień”. Sama formuła się nie zmienia; zmienia się to, co widzi.

Excelowa analogia: to obszar tabeli przestawnej, który po rozwinięciu podwójnym kliknięciem daje listę wierszy stojących za liczbą.

03

Kontekst wiersza

Pojawia się tylko w kolumnie obliczeniowej i wewnątrz funkcji iterujących (SUMX, AVERAGEX, FILTER). Oznacza „jesteśmy teraz na konkretnym wierszu tabeli i możemy odczytać jego pola”.

Kontekst wiersza sam z siebie nie filtruje reszty modelu. To najczęstsze źródło zdziwienia u osób przychodzących z Excela — bycie na wierszu faktury nie zawęża automatycznie żadnej innej tabeli.

04

Przejście kontekstu

Gdy wewnątrz kontekstu wiersza użyjesz CALCULATE (albo wywołasz miarę, bo miara jest w CALCULATE zapakowana automatycznie), bieżący wiersz zamienia się w filtr nałożony na cały model.

Dzięki temu SUMX(Dealerzy, [Przychód netto]) działa: dla każdego dealera przejście kontekstu zawęża sprzedaż do tego dealera. Bez tego mechanizmu dostałbyś tę samą sumę całkowitą powieloną tyle razy, ilu masz dealerów.

05

Model gwiazdy

Tabele faktów (Sprzedaz, Serwis, Produkcja) trzymają zdarzenia: dużo wierszy, dużo liczb. Tabele wymiarów (Kalendarz, Pojazdy, Dealerzy, Klienci) trzymają opisy: po czym chcesz kroić.

Filtruj zawsze po wymiarach, nigdy po kolumnach tabeli faktów. Miara napisana na modelu gwiazdy jest krótsza, czytelniejsza i liczy się w ułamku czasu.

Jedna szeroka tabela „bo tak było w Excelu” to najdroższa decyzja projektowa, jaką można podjąć w Power BI.

06

Tabela dat

Cała analiza czasowa (YTD, rok do roku, kroczące 12 miesięcy) wymaga osobnej tabeli kalendarza: ciągłej, bez luk, obejmującej pełne lata, oznaczonej w modelu jako Oznacz jako tabelę dat.

Kolumny Rok, Miesiac, RokMiesiac, RokFiskalny buduj w kalendarzu, nie w tabeli sprzedaży. Wtedy jedna oś czasu obsługuje sprzedaż, serwis i plan naraz.

Model danych używany we wszystkich przykładach

Każdy fragment kodu w tym podręczniku odwołuje się do tego samego modelu. Podmiana nazw na własne zajmuje minutę, a dzięki spójności widać, jak funkcje ze sobą współpracują.

TabelaRolaKluczowe kolumny
Kalendarzwymiar datData, Rok, Kwartal, Miesiac, RokMiesiac, RokFiskalny, NrMiesiaca
SprzedazfaktySalesID, DataSprzedazy, VIN, DealerID, ModelID, KlientID, Ilosc, CenaNetto, Rabat, KosztWlasny
PojazdywymiarModelID, Marka, Model, Wersja, Segment, TypNapedu, MocKM, EmisjaCO2, CenaKatalogowa
DealerzywymiarDealerID, NazwaDealera, Region, Wojewodztwo, TypPlacowki, Email
KlienciwymiarKlientID, TypKlienta (B2C / B2B / Flota), Segment, DataPierwszegoZakupu
SerwisfaktyZlecenieID, VIN, DataPrzyjecia, DataWydania, DealerID, TypNaprawy, KosztCzesci, KosztRobocizny, RoboczoGodziny
ProdukcjafaktyDataProdukcji, ZakladID, ModelID, SztukiWyprodukowane, SztukiWadliwe, CzasTaktu
MagazynsnapshotData, CzescID, StanMagazynowy, CenaJednostkowa
PlanbudżetRok, NrMiesiaca, DealerID, ModelID, PlanSztuki, PlanWartosc

Relacje: Kalendarz[Data] zasila Sprzedaz[DataSprzedazy] i Serwis[DataPrzyjecia] relacjami aktywnymi oraz Serwis[DataWydania] relacją nieaktywną. Tabela Plan celowo nie ma relacji fizycznej — łączymy ją przez TREATAS, bo ma inne ziarno niż sprzedaż (miesiąc zamiast dnia, model zamiast egzemplarza).

00A · SŁOWNIK

Excel → DAX. To, co już umiesz, tylko inaczej zapisane

Nie uczysz się liczyć od nowa — uczysz się innego zapisu tych samych operacji. Ta tabela to najkrótsza droga od „wiem, co chcę policzyć” do „wiem, jak to napisać”.

W Excelu robiszW DAX piszeszCo się zmienia w myśleniu
SUMA(zakres)SUM(Sprzedaz[Ilosc])Nie wskazujesz zakresu komórek, tylko całą kolumnę. Zakres wyznaczy kontekst filtra wizualizacji.
SUMA.JEŻELICALCULATE(SUM(...), Pojazdy[Segment]="SUV")Warunek nie stoi obok danych, tylko modyfikuje kontekst, w którym liczy się agregacja.
SUMA.WARUNKÓWCALCULATE(SUM(...), warunek1, warunek2)Kolejne argumenty CALCULATE łączą się operatorem „oraz”. Kolejność nie ma znaczenia.
SUMA.ILOCZYNÓWSUMX(Sprzedaz, Sprzedaz[Ilosc] * Sprzedaz[CenaNetto])Iterator mnoży wiersz po wierszu, a dopiero potem sumuje. To jedna z najważniejszych różnic.
WYSZUKAJ.PIONOWO do słownikaRELATED(Pojazdy[Segment])Relacja w modelu zastępuje funkcję wyszukiwania. Definiujesz ją raz, działa wszędzie.
WYSZUKAJ.PIONOWO bez relacjiLOOKUPVALUE(Dealerzy[Region], Dealerzy[DealerID], 42)Awaryjne wyjście, gdy relacji nie da się zbudować. Wolniejsze — używaj świadomie.
JEŻELI.BŁĄD(a/b; 0)DIVIDE(a, b, 0)Jedna funkcja zamiast opakowywania dzielenia w obsługę błędu. Szybsza i czytelniejsza.
LICZ.JEŻELICALCULATE(COUNTROWS(Sprzedaz), warunek)Zliczasz wiersze tabeli w zawężonym kontekście, nie komórki spełniające kryterium.
LICZ.UNIKATOWEDISTINCTCOUNT(Sprzedaz[VIN])Działa na kolumnie i respektuje wszystkie aktywne filtry. Uwaga na koszt przy dużych kardynalnościach.
% udziału w sumie kolumnyDIVIDE([Sztuki], CALCULATE([Sztuki], ALLSELECTED(...)))Mianownik trzeba świadomie „odfiltrować”. Excel robił to za ciebie, DAX wymaga decyzji.
Suma narastająco w kolumnieTOTALYTD([Przychód netto], Kalendarz[Data])Zamiast rozciągać formułę w dół, deklarujesz okres. Działa na każdym poziomie hierarchii dat.
Odwołanie do komórki obok (LAG)OFFSET(-1, ...) lub DATEADD(...)Nie ma „komórki obok”. Jest porządek sortowania i przesunięcie w nim.
Nazwane komórki pomocniczeVAR nazwa = ... RETURN ...Zmienne liczą się raz i porządkują formułę. To najlepszy nawyk, jaki możesz wyrobić na starcie.
Tabela przestawnaWizualizacja macierzyMiara jest wspólna dla wszystkich wizualizacji, więc definicję marży poprawiasz raz, a nie w ośmiu arkuszach.
Arkusz „Plan” obok „Wykonania”Tabela Plan + TREATASNie sklejasz danych w jedną płachtę. Zestawiasz dwie tabele o różnym ziarnie wspólnym wymiarem.
Ukrywanie zer formatowaniemBLANK() kontra 0Pusta wartość w DAX ukrywa cały wiersz wizualizacji. Czasem tego chcesz, czasem to ukrywa problem.
Nawyk na start Zanim napiszesz cokolwiek skomplikowanego, zbuduj trzy miary bazowe: Sztuki sprzedane, Przychód netto, Marża netto. Wszystkie kolejne miary — plan, dynamika, udziały, rankingi — powinny odwoływać się do nich, a nie powtarzać sumowanie. Zmiana definicji przychodu w jednym miejscu przeliczy wtedy cały raport.
CZĘŚĆ GŁÓWNA · KATALOG

Katalog funkcji

Każda pozycja ma kod, poziom trudności i przykład osadzony w modelu opisanym wyżej. Filtruj po poziomie, gdy chcesz zobaczyć wyłącznie to, co potrzebne na start, albo szukaj po nazwie funkcji i po treści opisu.

Nic nie pasuje do tego zapytania. Spróbuj krótszej frazy albo wyczyść filtr poziomu.

CZĘŚĆ DRUGA · WZORCE ŁĄCZONE

Dwanaście wzorców, z których składa się raport planisty

Pojedyncza funkcja rzadko rozwiązuje problem. Poniżej pełne rozwiązania złożone z kilku funkcji naraz, każde z rozbiorem na kroki — po to, żeby dało się je przerobić na własny model, a nie tylko skopiować.

CZĘŚĆ TRZECIA · USTERKI

Gdy wynik jest zły. Tabela objawów

Miary rzadko psują się losowo. Prawie każdy błędny wynik da się przypisać do jednej z poniższych przyczyn — zacznij od objawu, nie od czytania kodu od początku.

ObjawNajczęstsza przyczynaCo zrobić
Ta sama liczba powtarza się w każdym wierszu Miara nie reaguje na kontekst, bo filtr został zdjęty przez ALL albo warunek w CALCULATE nadpisał filtr wiersza Sprawdź, czy zamiast ALL nie powinno być ALLSELECTED, i czy warunek nie potrzebuje opakowania w KEEPFILTERS
Suma całkowita nie równa się sumie wierszy To normalne dla wskaźników nieaddytywnych: procentów, cen średnich, liczb unikalnych Nie „naprawiaj” liczby. Ukryj ją w wierszu sumy przez HASONEVALUE albo policz sumę osobnym wzorem
Wiersze znikają z tabeli Miara zwraca BLANK(), a wizualizacja ukrywa puste wiersze Użyj COALESCE(miara, 0), jeśli wiersz ma pozostać widoczny — na przykład dealer z planem, ale bez sprzedaży
Porównanie rok do roku jest puste Kalendarz nie jest oznaczony jako tabela dat, ma luki albo nie obejmuje pełnych lat Zbuduj kalendarz przez CALENDARAUTO, oznacz go w modelu i sprawdź, czy obejmuje 1 stycznia i 31 grudnia każdego roku
Plan pokazuje pustkę mimo danych w tabeli Niezgodność typów albo zapisu w kolumnach łączonych przez TREATAS Porównaj wartości po obu stronach: liczba kontra tekst, „01” kontra 1, spacje na końcu identyfikatora
Udziały procentowe nie sumują się do stu Mianownik policzony przez ALL, więc ignoruje wybór użytkownika w slicerach Zamień na ALLSELECTED — wtedy podstawą jest to, co użytkownik faktycznie widzi
Ranking wszędzie pokazuje jedynkę Brak ALL w pierwszym argumencie RANKX — porównanie odbywa się w obrębie jednego wiersza Dodaj ALL lub ALLSELECTED na kolumnie, po której budujesz ranking
Błąd o braku kontekstu wiersza Użycie RELATED albo odwołania do kolumny w mierze bez iteratora Opakuj wyrażenie w SUMX lub inny iterator, albo sięgnij po agregację zamiast pojedynczej wartości
Wynik zmienia się po dodaniu slicera, choć nie powinien Filtrowanie dwukierunkowe w relacji przenosi filtr tam, gdzie nie powinien dotrzeć Wyłącz filtrowanie dwukierunkowe w modelu i włączaj je punktowo przez CROSSFILTER w konkretnej mierze
Wizualizacja liczy się kilkanaście sekund FILTER na całej tabeli faktów albo DISTINCTCOUNT na kolumnie o wysokiej kardynalności Filtruj wymiary zamiast faktów, a przy zliczaniu unikalnych rozważ COUNTROWS(SUMMARIZE(...))
Miesiące sortują się alfabetycznie Kolumna nazwy miesiąca nie ma ustawionego sortowania według kolumny liczbowej W modelu ustaw sortowanie kolumny Miesiac według NrMiesiaca
Liczby zgadzają się w sumie, ale nie w przekrojach Agregat policzony na złym poziomie: SUM tam, gdzie potrzebny był SUMX Sprawdź, czy obliczenie nie wymaga danych z dwóch kolumn naraz — wtedy zawsze potrzebny jest iterator
CZĘŚĆ CZWARTA · KOLEJNOŚĆ NAUKI

Dziesięć kroków, w tej kolejności

Kolejność nie jest przypadkowa. Każdy krok opiera się na poprzednim, a próba przeskoczenia etapu z kontekstem filtra kończy się miesiącami zgadywania, dlaczego liczby nie chcą się zgodzić.

  1. Zbuduj kalendarz i oznacz go jako tabelę dat. Zanim policzysz cokolwiek. Bez tego połowa katalogu nie działa poprawnie.
  2. Napisz trzy miary bazowe ze wzorca W01 i sprawdź je na macierzy: sztuki, przychód, marża.
  3. Poczuj różnicę między SUM a SUMX. Policz przychód oboma sposobami i zobacz, dlaczego jeden wynik jest bez sensu.
  4. Naucz się CALCULATE z jednym warunkiem. Sprzedaż BEV, sprzedaż flotowa, sprzedaż jednego regionu.
  5. Zderz się z nadpisywaniem filtra. Wstaw miarę z warunkiem do macierzy po typach napędu i zobacz, co się stanie. Potem dodaj KEEPFILTERS.
  6. Policz pierwszy udział procentowy i porównaj wynik z ALL oraz ALLSELECTED przy włączonym slicerze.
  7. Dodaj analizę czasową: rok do roku i narastające, według wzorca W03.
  8. Podłącz plan przez TREATAS — wzorzec W02. To moment, w którym DAX zaczyna zarabiać na siebie w pracy planisty.
  9. Przepisz najdłuższą miarę na zmienne VAR. Zobaczysz, o ile łatwiej ją czytać i o ile szybciej działa.
  10. Zbuduj mostek cena–wolumen–miks ze wzorca W05 i sprawdź, czy kontrola zwraca zero. Jeśli tak, rozumiesz kontekst filtra.
Jedna rada na koniec Każdą nową miarę sprawdzaj w macierzy na trzech poziomach naraz: pojedynczy miesiąc, suma roku i suma całkowita. Osiemdziesiąt procent błędów w DAX ujawnia się dopiero w wierszu sumy — i tylko tam.