У DAX есть репутация сложного языка. Справедливо: контексты фильтров, время вычислений, взаимодействие с моделью — там есть куда закапываться. Но для 90% управленческой отчётности достаточно 15-20 формул, которые закрывают типовые бизнес-вопросы.
Эта статья — справочник для двух аудиторий: финдиректор/BI-лид, который хочет понимать, что просит у разработчика; и junior-аналитик, которому нужна шпаргалка production-формул. Каждая формула — с разбором бизнес-вопроса и типичной ошибки (которую мы видим на аудитах снова и снова).
Допущения по модели: есть fact_sales (order_date, выручка, cogs, customer_id, product_id, region_id), dim_date (помечена как Date Table), dim_product, dim_region. Базовые меры [Revenue] и [COGS] уже определены через SUM.
Блок 01 · Time intelligence
Выручка с начала года
«Сколько мы продали с 1 января по текущую дату?»
Revenue YTD =
TOTALYTD(
[Revenue],
dim_date[date]
)
TOTALYTD возвращает сумму с начала календарного года до текущего контекста даты. Если ваш финансовый год не совпадает с календарным (например, начинается 1 апреля), добавьте третий аргумент: "31/03" — конец финансового года.
Изменение к прошлому году
«Как изменилась выручка по сравнению с тем же периодом год назад?»
Revenue LY =
CALCULATE(
[Revenue],
SAMEPERIODLASTYEAR(dim_date[date])
)
Revenue YoY % =
DIVIDE(
[Revenue] - [Revenue LY],
[Revenue LY]
)
SAMEPERIODLASTYEAR сдвигает контекст даты ровно на год назад. Если смотрите на январь 2026 — показывает январь 2025.
С начала месяца / квартала
«Сколько с начала этого месяца? С начала квартала?»
Revenue MTD =
TOTALMTD([Revenue], dim_date[date])
Revenue QTD =
TOTALQTD([Revenue], dim_date[date])
Симметричны TOTALYTD, но за месяц и квартал соответственно. Очень востребованы в операционных дашбордах, где следят за внутримесячной динамикой.
Сумма за последние 12 месяцев (скользящее)
«Какая у нас выручка за последний год — не YTD, а скользящий год к текущей дате?»
Revenue R12M =
CALCULATE(
[Revenue],
DATESINPERIOD(
dim_date[date],
MAX(dim_date[date]),
-12,
MONTH
)
)
DATESINPERIOD строит диапазон от указанной даты назад. На графиках по месяцам даёт классическую «скользящую годовую», которая сглаживает сезонность и хорошо показывает реальный тренд.
Предыдущий период (месяц, квартал, год)
«А как было в прошлом месяце? В прошлом квартале?»
Revenue PM =
CALCULATE(
[Revenue],
PREVIOUSMONTH(dim_date[date])
)
Revenue PQ =
CALCULATE(
[Revenue],
PREVIOUSQUARTER(dim_date[date])
)
PREVIOUSMONTH/PREVIOUSQUARTER/PREVIOUSYEAR — готовые функции для сдвига на один период назад. Быстрее и читаемее, чем самодельные конструкции через DATEADD.
Блок 02 · Сравнения и доли
Доля в общей сумме
«Какую долю в выручке занимает каждая категория?»
Revenue % of Total =
DIVIDE(
[Revenue],
CALCULATE(
[Revenue],
REMOVEFILTERS(dim_product[category])
)
)
Знаменатель — выручка без фильтра по категории (всё остальное сохранено). Делим текущую выручку на общий итог.
ALL(dim_product) вместо REMOVEFILTERS по конкретной колонке — снимутся все фильтры на dim_product, включая бренд, подкатегорию. Доля посчитается некорректно. См. пуск про REMOVEFILTERS vs ALL.Маржа и её процент
«Какая маржинальность по категориям? Какой абсолютный margin contribution?»
Gross Margin =
[Revenue] - [COGS]
Gross Margin % =
DIVIDE(
[Revenue] - [COGS],
[Revenue]
)
Базовая мера для финансовой отчётности. Обычно комбинируется с % от общего и YoY — получается полноценный margin breakdown.
Процент изменения между двумя величинами
«На сколько процентов факт отличается от плана? Или от прошлого периода?»
// Универсальная форма
Variance % =
DIVIDE(
[Actual] - [Baseline],
ABS([Baseline])
)
// Пример для план-факт
Variance Plan-Fact % =
DIVIDE(
[Revenue] - [Revenue Plan],
ABS([Revenue Plan])
)
ABS в знаменателе важен: если базовый уровень может быть отрицательным (убыток, затраты), без ABS знак вариации получится противоположным от интуитивного.
Доля внутри группы
«Какая доля продукта внутри своей категории?»
Revenue % of Category =
DIVIDE(
[Revenue],
CALCULATE(
[Revenue],
REMOVEFILTERS(dim_product[product_name])
)
)
Отличается от формулы 06 тем, что снимается фильтр только на уровне продукта. Фильтр по категории сохраняется, поэтому знаменатель — это выручка всех продуктов в текущей категории.
Полезно для дерева долей: % в категории × % категории в общем = % продукта в общем.
Блок 03 · Ранжирование и top-N
Место в рейтинге
«Какое место у этого региона по выручке?»
Region Rank =
RANKX(
ALL(dim_region),
[Revenue],
,
DESC,
DENSE
)
Четвёртый аргумент — направление (ASC/DESC). Пятый — как обрабатывать одинаковые значения: SKIP (пропускать номера: 1,2,2,4) или DENSE (без пропусков: 1,2,2,3). Для управленческих отчётов обычно DESC + DENSE.
Показать top-5, остальное свернуть в «Прочие»
«Покажите топ-5 продуктов по выручке, остальные одной строкой "Прочие"»
Top5 Revenue =
VAR _rank =
RANKX(
ALL(dim_product[product_name]),
[Revenue],
, DESC, DENSE
)
RETURN
IF(
_rank <= 5,
[Revenue],
BLANK()
)
Others Revenue =
CALCULATE(
[Revenue],
FILTER(
ALL(dim_product),
RANKX(
ALL(dim_product[product_name]),
[Revenue],
, DESC, DENSE
) > 5
)
)
Сложнее классического RANKX, но даёт возможность отрисовать на графике топ-5 отдельными столбцами плюс «Прочие» сумарно. Без этого паттерна визуал с 100+ продуктами выглядит нечитаемо.
ABC по вкладу в общую сумму
«Разнесите все товары по классам A/B/C: A — первые 80% выручки, B — следующие 15%, C — оставшиеся 5%»
ABC Class =
VAR _total_revenue =
CALCULATE(
[Revenue],
ALL(dim_product)
)
VAR _cum_share =
DIVIDE(
CALCULATE(
[Revenue],
FILTER(
ALL(dim_product),
[Revenue] >= EARLIER([Revenue])
)
),
_total_revenue
)
RETURN
SWITCH(
TRUE(),
_cum_share <= 0.80, "A",
_cum_share <= 0.95, "B",
"C"
)
Считает накопительную долю каждого товара в общей выручке и раскладывает по классам. Тяжёлый запрос для больших каталогов — на моделях >50 тыс. SKU имеет смысл выносить ABC-класс в ETL как заранее рассчитанную колонку в dim_product.
Блок 04 · План-факт и прогноз
Базовая мера план-факт
«Выполняем план по выручке или нет? На сколько отстаём/обгоняем?»
// предполагаем, что есть fact_plan с [plan_revenue]
Plan Fulfillment % =
DIVIDE(
[Revenue],
[Revenue Plan]
)
Plan Delta =
[Revenue] - [Revenue Plan]
Plan Status =
SWITCH(
TRUE(),
[Plan Fulfillment %] >= 1.0, "✓ План выполнен",
[Plan Fulfillment %] >= 0.9, "⚠ Близко",
"✗ Провал"
)
Комбинация из трёх мер: процент, абсолютное отклонение и статус. На дашборде управленца все три обычно рядом.
Накопительный итог с начала периода
«Как нарастает выручка с начала года по дням/неделям?»
Revenue Running =
CALCULATE(
[Revenue],
FILTER(
ALL(dim_date),
dim_date[date] <= MAX(dim_date[date])
)
)
Стандартная накопительная сумма. Визуально — плавно растущая кривая, которая ярко показывает темп выполнения плана по году.
Добавьте рядом плановую накопительную (такой же running, но от [выручка Plan]) — и получите классический график CFO «факт против плана по нарастанию».
Простой прогноз на остаток периода
«Если темп текущего месяца сохранится, куда придём к концу месяца?»
Forecast MTD to Month End =
VAR _days_passed =
COUNTROWS(
FILTER(
dim_date,
dim_date[date] <= TODAY()
&& MONTH(dim_date[date]) = MONTH(TODAY())
&& YEAR(dim_date[date]) = YEAR(TODAY())
)
)
VAR _days_total =
DAY(EOMONTH(TODAY(), 0))
VAR _mtd_revenue = [Revenue MTD]
RETURN
DIVIDE(_mtd_revenue, _days_passed) * _days_total
Берёт выручку с начала месяца, делит на прошедшие дни, умножает на длину всего месяца. Получается наивный прогноз на конец месяца при сохранении текущего темпа. Грубо, но для операционного контроля работает — главное, что сигнал виден заранее, а не 1-го числа следующего месяца.
Как запомнить и где применять
Этими 15 формулами закрывается бо́льшая часть управленческих отчётов среднего бизнеса: P&L по периодам, дашборды продаж, операционные сводки, план-факт. Держите шпаргалку под рукой — в DAX Cheat Sheet собрано то же самое + ещё 10 формул для HR, закупок, финансового моделирования. Файл можно распечатать и положить рядом с монитором.
Для освоения хватит пары вечеров практики: возьмите свою модель, прогоните по ней каждую формулу из списка. После этого вопросы «как посчитать X» начинают решаться сами.
Если видите, что готовые формулы работают медленно — прочитайте P13 про рефакторинг Power BI: там подробно про VAR, REMOVEFILTERS, bi-directional и остальные ускоряющие паттерны. Многие проблемы производительности — это не «формула неправильная», а «формула написана без учёта того, как движок её исполняет».
Что делать дальше
- Для внутренней команды — скачайте DAX Cheat Sheet, распечатайте, раздайте аналитикам. Сэкономит им часы поиска по документации.
- Если нужно обучение — проводим 2-3 сессии по DAX и SSAS для вашего сотрудника. Формат — практика на вашей реальной модели. 50-100 тыс. ₽ в зависимости от объёма.
- Если отчёты тормозят после появления новых формул — 5-дневный аудит найдёт проблемные меры и даст план рефакторинга.
Связанные материалы:
- Power BI для среднего бизнеса — архитектура, SSAS, где DAX вписывается
- Рефакторинг Power BI в 10 раз — оптимизация DAX-формул
- RLS на SSAS Tabular — безопасность через DAX-роли