Обычный SUM сворачивает готовый столбец. Но часто нужного столбца нет — значение надо собрать по каждой строке, а потом просуммировать. Для этого есть итераторы: те же функции, но с буквой X на конце — SUMX, AVERAGEX, COUNTX, MINX, MAXX.
Как работает итератор
SUMX делает два шага: проходит таблицу строка за строкой, вычисляет выражение для каждой строки, а потом складывает результаты.
Выручка (из количества и цены) =
SUMX ( Продажи, Продажи[Количество] * RELATED ( Товары[Цена] ) )
Для каждой строки продаж берётся количество, умножается на цену товара — и всё это суммируется. (RELATED тянет цену из справочника Товары; подробно — в уроке про связи, пока читайте как «цена этого товара».)
В нашем наборе столбец Сумма уже посчитан, поэтому результат совпадёт с SUM(Продажи[Сумма]). Но идея важна: если бы готовой суммы не было, итератор собрал бы её сам. Так считают маржу (Количество * (Цена − Себестоимость)), вес, объём — всё, где число рождается в строке.
Если расчёт можно сделать на уже готовом столбце — берите обычный SUM. Если значение нужно вычислить в каждой строке (умножить два столбца, применить условие к строке) — нужен SUMX или другой итератор.
AVERAGEX и настоящий средний чек
Помните ловушку из прошлого урока: AVERAGE(Продажи[Сумма]) — это среднее по строкам, а не средний чек. Итератор решает это правильно:
Средний чек =
AVERAGEX ( VALUES ( Продажи[НомерЗаказа] ), [Выручка] )
Читается так: пройди по уникальным заказам (VALUES даёт список номеров), для каждого посчитай [Выручка], и усредни эти суммы заказов. Теперь это честный средний чек — среднее по заказам, а не по строкам.
Когда итератор стоит на конкретном заказе, этот заказ становится контекстом — и [Выручка] считается только по нему. Это «переход контекста»: итератор превращает текущую строку в фильтр. Деталь продвинутая, но именно она заставляет средний чек считаться правильно.
Цена итераторов
Итератор перебирает строки по одной — на больших фактах это дороже, чем SUM. Правило простое:
- нужен расчёт на готовом столбце →
SUM(дёшево); - нужен расчёт, зависящий от строки →
SUMX/AVERAGEX(дороже, но необходимо).
Не превращайте SUM(Продажи[Сумма]) в SUMX(Продажи, Продажи[Сумма]) без причины — это лишняя работа на ровном месте.
Семейство X
У большинства агрегаций есть X-версия: SUMX, AVERAGEX, MINX, MAXX, COUNTX, RANKX, CONCATENATEX. Все устроены одинаково: первый аргумент — таблица, по которой идём, второй — выражение, которое считаем в каждой строке.
Цена лежит в Товары, а не в Продажи. Посчитайте выручку итератором: Выручка SUMX = SUMX ( Продажи, Продажи[Количество] * RELATED ( Товары[Цена] ) ). Должна ли она совпасть с SUM ( Продажи[Сумма] )?
Показать ответ
Да, обе дают 9 826 588 ₽. В наборе Сумма = Количество × Цена, поэтому построчный пересчёт через SUMX совпадает с готовой суммой. Если не совпало — забыли RELATED (цена не подтянулась из Товары).
Что дальше
Мы умеем сворачивать столбцы и считать построчно. Но всё это — в том контексте, который дал отчёт. А что, если контекст нужно поменять прямо в мере — посчитать «по молочке» независимо от среза? Для этого есть самая мощная функция DAX — CALCULATE. Следующий урок.