Если ты пришёл на собес в Яндекс / Магнит / Сбер / X5 и тебя спросили «объясни разницу между CALCULATE и FILTER в DAX» — это значит, у них есть Power BI и команда BI-аналитиков. DAX (Data Analysis Expressions) — язык формул Power BI, и его понимание отличает аналитика, который может строить дашборды, от того, кто умеет только Excel.
Этот гайд — практическое введение в DAX через 6 реальных примеров мер, которые ты встретишь на любом enterprise-проекте.
Что такое DAX и зачем он аналитику
DAX — это язык формул, который Power BI (и Excel Power Pivot, и SQL Server Analysis Services Tabular) использует для расчёта мер и вычисляемых колонок.
Звучит просто, но есть критическая концепция: DAX оценивает выражение в контексте. Контекст бывает двух типов:
- Row context — текущая строка таблицы (например, при iter'ации через SUMX)
- Filter context — какие фильтры применяются в визуале / срезе
CALCULATE — это функция, которая меняет filter context. Понимание этого = 80% работы DAX.
ROW vs FILTER context: главное различие
Row context — про текущую строку
-- Calculated column в таблице Sales
Margin = Sales[Revenue] - Sales[Cost]
DAX берёт текущую строку и считает разницу. Просто.
Filter context — про срезы визуала
-- Measure
Total Revenue = SUM(Sales[Revenue])
DAX смотрит на фильтры визуала (год = 2026, регион = «Москва») и суммирует только подходящие строки.
Context transition: row → filter
Это магия CALCULATE. Внутри row context (например, в SUMX iter) если ты вызываешь measure — DAX автоматически переводит row context в filter context.
Sales Per Customer =
SUMX(
Customers,
[Total Revenue] -- эта measure внутри iter'а использует CALCULATE неявно
)
Понимание context transition = senior-уровень DAX.
CALCULATE — самая важная функция
Синтаксис:
CALCULATE(<expression>, <filter1>, <filter2>, ...)
Что делает:
- Берёт current filter context
- Накладывает дополнительные фильтры
- Считает expression в этом modified context
Пример 1. Sales за прошлый год
Revenue PY =
CALCULATE(
[Total Revenue],
SAMEPERIODLASTYEAR(Dates[Date])
)
CALCULATE говорит: «посчитай Total Revenue, но фильтр Dates сдвинь на год назад».
Пример 2. Sales только в Москве
Moscow Revenue =
CALCULATE(
[Total Revenue],
Geo[City] = "Москва"
)
Накладывает доп. фильтр Geo[City] = "Москва" поверх существующих.
Пример 3. Sales по всем регионам (override любого фильтра)
Total Revenue All =
CALCULATE(
[Total Revenue],
ALL(Geo)
)
ALL убирает фильтры на Geo — даёт total по всем регионам, даже если в визуале выбран один.
SUMX — iteration с row context
SUMX iter'ирует таблицу и считает выражение для каждой строки, потом суммирует.
Пример 4. Margin с учётом скидки на каждую строку
Total Margin =
SUMX(
Sales,
Sales[Revenue] * (1 - Sales[Discount]) - Sales[Cost]
)
Зачем не SUM? Потому что нужно считать в row context — discount может быть разный для каждой строки. Простой SUM(Sales[Revenue]) * (1 - AVG(Sales[Discount])) даст неправильный результат (среднее discount ≠ применить discount на каждую строку).
RANKX — ранжирование
Customer Rank =
RANKX(
ALL(Customers[Name]),
[Total Revenue],
,
DESC,
DENSE
)
ALL(Customers[Name]) — снимает фильтр на текущего customer'а (иначе rank всегда будет 1).
Шаг 1: Создай measure-таблицу
В Power BI Desktop сделай отдельную таблицу Measures (через Enter Data). Это convention — все measures хранятся в одном месте, не разбросаны по data-таблицам.
Шаг 2: Напиши базовые measures
Total Revenue = SUM(Sales[Revenue])
Total Cost = SUM(Sales[Cost])
Total Margin = [Total Revenue] - [Total Cost]
Margin % = DIVIDE([Total Margin], [Total Revenue])
DIVIDE — встроенный safe-divide. Лучше A / B потому что обрабатывает деление на 0.
Шаг 3: Time intelligence
Revenue YTD =
CALCULATE(
[Total Revenue],
DATESYTD(Dates[Date])
)
Revenue MoM Growth % =
DIVIDE(
[Total Revenue] - CALCULATE([Total Revenue], DATEADD(Dates[Date], -1, MONTH)),
CALCULATE([Total Revenue], DATEADD(Dates[Date], -1, MONTH))
)
Шаг 4: Comparative measures
Revenue vs PY =
[Total Revenue] - [Revenue PY]
Revenue vs Target =
[Total Revenue] - SUM(Targets[Target])
Шаг 5: Running totals
Running Revenue =
CALCULATE(
[Total Revenue],
FILTER(
ALL(Dates[Date]),
Dates[Date] <= MAX(Dates[Date])
)
)
ALL(Dates[Date]) снимает фильтр на текущий период, FILTER оставляет все даты до max'а в визуале.
Шаг 6: Top-N с RANKX
Top 10 Products Revenue =
IF(
RANKX(ALL(Products[Name]), [Total Revenue], , DESC) <= 10,
[Total Revenue],
BLANK()
)
DAX vs SQL — что когда
| Когда DAX | Когда SQL |
|---|---|
| Финальные measures для визуала | Подготовка таблиц до DAX |
| Time intelligence (YTD, MoM, YoY) | Когортный анализ, ETL |
| Conditional measures (если-то) | Window functions, complex JOIN |
| RLS (Row-Level Security) | DDL, индексы, performance |
Правило: не делай в DAX то, что можно сделать в SQL/dbt. Чем легче data model, тем быстрее работает Power BI.
Частые вопросы
CALCULATE vs FILTER — в чём разница?
CALCULATE меняет filter context для expression. FILTER возвращает отфильтрованную таблицу — обычно используется внутри CALCULATE как аргумент-фильтр для сложных условий.
-- Простой фильтр через CALCULATE
CALCULATE([Revenue], Sales[Region] = "Moscow")
-- Сложный фильтр через FILTER
CALCULATE([Revenue], FILTER(Sales, Sales[Region] = "Moscow" && Sales[Amount] > 1000))
Когда использовать SUMX вместо SUM?
Когда нужно per-row вычисление. SUM суммирует одну колонку. SUMX iter'ирует таблицу и суммирует выражение, которое может включать несколько колонок.
Что такое DIVIDE и почему не / ?
DIVIDE — это safe-divide, обрабатывает деление на 0 (возвращает BLANK или указанное значение). Обычный / даёт ошибку Infinity которая ломает visual.
Как DAX отличается от M (Power Query)?
M (Power Query) — про ETL: загрузка, очистка, transformation данных. DAX — про analytics: measures, calculated columns, RLS. M запускается один раз при refresh, DAX — каждый раз при interaction с визуалом.
Что значит «context transition»?
Когда DAX внутри row context (например, в SUMX) вызывает measure — он автоматически преобразует current row в filter context. То есть для текущей строки накладывает фильтры по всем её значениям. Без этого SUMX(Customers, [Revenue]) считал бы Revenue одинаково для всех customer'ов.
Связанные ресурсы
- 🧪 BI-песочница — наш аналог Power BI / Tableau / DataLens, без установки
- 📊 Tableau LOD на примерах — конкурирующий стек
- 📝 Yandex DataLens пошагово — RU-альтернатива Power BI
- 🎯 Tableau / Power BI / DataLens / Superset сравнение
- 💼 Топ-50 вопросов с собеса аналитика
Источники
- Microsoft Learn: «DAX overview» (learn.microsoft.com/dax)
- Marco Russo, Alberto Ferrari: «The Definitive Guide to DAX»
- SQLBI: «Understanding context transition» (sqlbi.com)
- Habr: «DAX-формулы Power BI 2026» (habr.com)
Хочешь практику без установки Power BI? Открой BI-песочницу — там 161 бизнес-задача по построению дашбордов с AI-оценкой по 5 критериям. Бесплатные первые 5.