CALCULATE — главная функция DAX
Осваиваем CALCULATE — функцию, которая меняет контекст фильтра и открывает всю мощь DAX.
CALCULATE вычисляет выражение в изменённом контексте фильтра, заданном дополнительными условиями.
Почему CALCULATE — сердце DAX
Все агрегаты до сих пор считались «в том фильтре, что есть». Но аналитику постоянно нужно сравнивать: выручка этого региона против всех, продажи только премиум-товаров, доля в общем итоге. Для этого фильтр нужно изменить прямо в формуле — и единственная функция, которая это умеет, — CALCULATE. Понять её — значит понять DAX.
Синтаксис
CALCULATE( <выражение>, <фильтр1>, <фильтр2>, ... )Первый аргумент — что считаем (обычно мера или агрегат). Дальше — условия, которые добавляются к текущему контексту фильтра (или заменяют его по столбцу). Примеры:
Выручка премиум = CALCULATE( [Выручка], Product[segment] = "Premium" )
Выручка всего = CALCULATE( [Выручка], ALL(Product) )
Доля сегмента = DIVIDE( [Выручка], CALCULATE([Выручка], ALL(Product)) )Первая мера считает выручку, дополнительно отфильтровав товары премиум-сегмента. Вторая — снимает все фильтры с таблицы Product функцией ALL (получаем «итог по всем товарам» независимо от среза). Третья делит одно на другое и даёт долю сегмента в общем — классический приём «процент от итога».
Как CALCULATE меняет контекст
Было (контекст фильтра): регион = Юг
│
▼ CALCULATE( [Выручка], Product[segment]="Premium" )
Стало: регион = Юг И segment = Premium
│
▼ CALCULATE( [Выручка], ALL(Product) )
Стало: регион = Юг (фильтр по Product СНЯТ функцией ALL)Запомните два режима: обычный фильтр сужает контекст (добавляет условие), а функции семейства ALL / REMOVEFILTERS снимают фильтры с указанных таблиц или столбцов. Комбинируя их, вы получаете любые сравнения.
FILTER для сложных условий
Если условие сложнее простого равенства, внутрь CALCULATE кладут функцию FILTER, возвращающую таблицу нужных строк:
Крупные продажи = CALCULATE(
[Выручка],
FILTER( Sales, Sales[amount] > 10000 )
)| Модификатор | Что делает с фильтром |
Стол[поле]=знач | добавляет условие (сужает) |
ALL(Таблица) | снимает все фильтры с таблицы |
REMOVEFILTERS() | то же, более явно |
FILTER(...) | произвольное условие как таблица |
Как работает под капотом
У CALCULATE есть скрытая суперспособность — context transition: она превращает текущий контекст строки в контекст фильтра. Поэтому когда меру (внутри которой неявно есть CALCULATE) вызывают в итераторе, она «знает» текущую строку как фильтр. Это объясняет, почему меры корректно работают в матрицах: каждая ячейка через переход контекста становится набором фильтров, и движок считает агрегат именно для неё.
Частые ошибки
- Думать, что CALCULATE всегда заменяет фильтр. Простые условия добавляются к текущим; чтобы заменить — снимайте старые через
ALL. - Считать «процент от итога» без
ALL. Без снятия фильтра знаменатель равен числителю, и доля всегда 100%. - Грузить тяжёлый
FILTERтам, где хватит простого условия. Простое равенство быстрее, чем итерация по всей таблице.
Итог
CALCULATEсчитает выражение в изменённом контексте фильтра — это её единственное, но всемогущее назначение.- Простые условия сужают контекст;
ALL/REMOVEFILTERSснимают фильтры (нужно для «процента от итога»). - Сложные условия задают через
FILTER; под капотом CALCULATE делает переход контекста строки в фильтр.