Porady. Pandas. Python. Django. Microsoft Power BI. Tableau.

DAX. Analiza i praca z datami

12.2024 | dax | power bi | dax obsługa dat

DAX (Data Analysis Expressions) oferuje potężne narzędzia do pracy z datami, które są kluczowe w analizie biznesowej. Ten przewodnik pomoże Ci zrozumieć i efektywnie wykorzystywać funkcje czasowe w DAX.

1. Podstawowe funkcje dat

Funkcje tworzące daty

// Dzisiejsza data
TODAY()

// Aktualna data i czas
NOW()

// Tworzenie daty z komponentów
DATE(rok, miesiąc, dzień)

// Data z tekstu
DATEVALUE("2024-01-01")

Wyodrębnianie komponentów dat

// Rok z daty
YEAR('Tabela'[Data])

// Miesiąc z daty
MONTH('Tabela'[Data])

// Dzień z daty
DAY('Tabela'[Data])

// Kwartał
QUARTER('Tabela'[Data])

// Numer tygodnia
WEEKNUM('Tabela'[Data])

Modyfikowanie dat

// Dodawanie dni
DATEADD('Tabela'[Data], 7, DAY)

// Dodawanie miesięcy
DATEADD('Tabela'[Data], 1, MONTH)

// Dodawanie lat
DATEADD('Tabela'[Data], 1, YEAR)

// Koniec miesiąca
EOMONTH('Tabela'[Data], 0)

2. Tworzenie tabeli kalendarza

Podstawowa tabela kalendarza

Kalendarz =
VAR MinData = MIN('Fakty'[Data])
VAR MaxData = MAX('Fakty'[Data])
RETURN
ADDCOLUMNS(
    CALENDAR(MinData, MaxData),
    "Rok", YEAR([Date]),
    "Miesiąc", MONTH([Date]),
    "DzieńTygodnia", WEEKDAY([Date], 2),
    "NazwaMiesiąca", FORMAT([Date], "mmmm"),
    "RokMiesiąc", FORMAT([Date], "yyyy-mm"),
    "Kwartał", "Q" & QUARTER([Date])
)

Zaawansowana tabela kalendarza

KalendarzZaawansowany =
VAR MinData = MIN('Fakty'[Data])
VAR MaxData = MAX('Fakty'[Data])
RETURN
ADDCOLUMNS(
    CALENDAR(MinData, MaxData),
    "Rok", YEAR([Date]),
    "Miesiąc", MONTH([Date]),
    "DzieńTygodnia", WEEKDAY([Date], 2),
    "NazwaMiesiąca", FORMAT([Date], "mmmm"),
    "RokMiesiąc", FORMAT([Date], "yyyy-mm"),
    "Kwartał", "Q" & QUARTER([Date]),
    "RokFiskalny",
        VAR MiesiacFiskalny = MONTH([Date])
        RETURN IF(
            MiesiacFiskalny >= 7,
            YEAR([Date]) + 1,
            YEAR([Date])
        ),
    "KwartałFiskalny",
        VAR MiesiacFiskalny = MONTH([Date])
        RETURN "FQ" & ROUNDUP((MOD(MiesiacFiskalny + 5, 12) + 1) / 3, 0),
    "JestDzieńRoboczy",
        NOT(WEEKDAY([Date], 2) IN {6, 7})
)

3. Inteligentne miary czasowe

Porównania okresów

// Sprzedaż w poprzednim miesiącu
SprzedażPoprzedniMiesiąc =
CALCULATE(
    [Sprzedaż],
    DATEADD('Kalendarz'[Data], -1, MONTH)
)

// Sprzedaż rok temu
SprzedażRokTemu =
CALCULATE(
    [Sprzedaż],
    SAMEPERIODLASTYEAR('Kalendarz'[Data])
)

// Zmiana procentowa rok do roku
ZmianaRokDoRoku =
VAR SprzedażBieżąca = [Sprzedaż]
VAR SprzedażPoprzednia = [SprzedażRokTemu]
RETURN
DIVIDE(
    SprzedażBieżąca - SprzedażPoprzednia,
    SprzedażPoprzednia,
    BLANK()
)

Narastająco od początku okresu

// Narastająco w roku
SprzedażNarastającoRok =
CALCULATE(
    [Sprzedaż],
    DATESYTD('Kalendarz'[Data])
)

// Narastająco w kwartale
SprzedażNarastającoKwartał =
CALCULATE(
    [Sprzedaż],
    DATESQTD('Kalendarz'[Data])
)

// Narastająco w miesiącu
SprzedażNarastającoMiesiąc =
CALCULATE(
    [Sprzedaż],
    DATESMTD('Kalendarz'[Data])
)

4. Analiza rok do roku (YoY)

Podstawowe porównania YoY

// Prosty YoY
ZmianaRoR =
DIVIDE(
    [Sprzedaż] - [SprzedażRokTemu],
    [SprzedażRokTemu],
    BLANK()
)

// YoY z wieloma miarami
AnalizaRoR =
VAR SprzedażBieżąca = [Sprzedaż]
VAR SprzedażPoprzednia = [SprzedażRokTemu]
VAR Zmiana = SprzedażBieżąca - SprzedażPoprzednia
VAR ZmianaProc = DIVIDE(Zmiana, SprzedażPoprzednia, BLANK())
RETURN
SWITCH(
    TRUE(),
    ZmianaProc > 0.1, "Znaczący wzrost",
    ZmianaProc > 0, "Wzrost",
    ZmianaProc < -0.1, "Znaczący spadek",
    ZmianaProc < 0, "Spadek",
    "Bez zmian"
)

Zaawansowane porównania YoY

// YoY z uwzględnieniem dni roboczych
ZmianaRoRSkorygowana =
VAR DniRoboczeBieżące =
    CALCULATE(
        COUNTROWS('Kalendarz'),
        'Kalendarz'[JestDzieńRoboczy] = TRUE
    )
VAR DniRoboczePoprzednie =
    CALCULATE(
        COUNTROWS('Kalendarz'),
        'Kalendarz'[JestDzieńRoboczy] = TRUE,
        SAMEPERIODLASTYEAR('Kalendarz'[Data])
    )
VAR SprzedażDzienna = DIVIDE([Sprzedaż], DniRoboczeBieżące)
VAR SprzedażDziennaPoprzednia =
    DIVIDE([SprzedażRokTemu], DniRoboczePoprzednie)
RETURN
DIVIDE(
    SprzedażDzienna - SprzedażDziennaPoprzednia,
    SprzedażDziennaPoprzednia,
    BLANK()
)

6. Obliczenia narastające

Różne typy obliczeń narastających

// Moving Annual Total (MAT)
MAT =
CALCULATE(
    [Sprzedaż],
    DATESINPERIOD(
        'Kalendarz'[Data],
        LASTDATE('Kalendarz'[Data]),
        -12,
        MONTH
    )
)

// Moving Quarter Total (MQT)
MQT =
CALCULATE(
    [Sprzedaż],
    DATESINPERIOD(
        'Kalendarz'[Data],
        LASTDATE('Kalendarz'[Data]),
        -3,
        MONTH
    )
)

// Średnia krocząca 3-miesięczna
ŚredniaKrocząca3M =
AVERAGEX(
    DATESINPERIOD(
        'Kalendarz'[Data],
        LASTDATE('Kalendarz'[Data]),
        -3,
        MONTH
    ),
    [Sprzedaż]
)

6. Przykłady praktyczne

Analiza sezonowości

// Indeks sezonowości
IndeksSezonowości =
VAR ŚredniaMiesięczna =
    CALCULATE(
        AVERAGE([Sprzedaż]),
        ALL('Kalendarz')
    )
RETURN
DIVIDE(
    [Sprzedaż],
    ŚredniaMiesięczna,
    BLANK()
)

// Wykrywanie szczytów sprzedaży
SzczytSprzedaży =
VAR MaxSprzedaż =
    CALCULATE(
        MAX([Sprzedaż]),
        ALL('Kalendarz')
    )
RETURN
IF(
    [Sprzedaż] = MaxSprzedaż,
    "Szczyt",
    "Normal"
)

Analiza dni roboczych

// Średnia dzienna sprzedaż
ŚredniaDziennaSprzedaż =
VAR DniRobocze =
    CALCULATE(
        COUNTROWS('Kalendarz'),
        'Kalendarz'[JestDzieńRoboczy] = TRUE
    )
RETURN
DIVIDE(
    [Sprzedaż],
    DniRobocze,
    BLANK()
)

7. Optymalizacja i najlepsze praktyki

Wskazówki wydajnościowe

  1. Używaj relacji między tabelami zamiast funkcji LOOKUPVALUE
  2. Preferuj CALCULATE z filtrami dat zamiast złożonych wyrażeń
  3. Unikaj zagnieżdżonych funkcji CALCULATE tam, gdzie to możliwe
  4. Używaj zmiennych (VAR) do przechowywania wyników pośrednich
  5. Optymalizuj tabelę kalendarza pod kątem potrzeb raportowych

Najczęstsze błędy

  1. Nieprawidłowe relacje między tabelami
  2. Brak obsługi wartości NULL w obliczeniach
  3. Niewłaściwe użycie kontekstu filtra
  4. Zbyt skomplikowane wyrażenia czasowe
  5. Brak indeksowania kolumn dat

Dobre praktyki

  1. Zawsze używaj dedykowanej tabeli kalendarza
  2. Standaryzuj nazewnictwo miar czasowych
  3. Dokumentuj złożone obliczenia czasowe
  4. Testuj miary na różnych poziomach granulacji
  5. Regularnie weryfikuj wydajność miar czasowych

Podsumowanie

Efektywna praca z datami w DAX wymaga:

  • Zrozumienia kontekstu obliczeniowego
  • Właściwego projektowania tabeli kalendarza
  • Znajomości funkcji czasowych
  • Stosowania dobrych praktyk optymalizacyjnych
  • Regularnego testowania i walidacji wyników

 

Wdrażam rozwiązania analityczne, buduję raporty zarządcze i pomagam zrozumieć dane.

Korzystam z Google Marketing Cloud, Microsoft Power BI, Google Cloud oraz Python.

Pracowałem m.in. dla Credit Suisse, Phonak, Hansaton, Unitron, Nestle, IBM, Play.

Jestem współtwórcą grupy Hexe Capital SA.

Zapraszam do lektury i współpracy.

Krzysztof Surowiecki

Chcę porozmawiać o współpracy →

Moje certyfikaty