Содержание статьи: (кликните, чтобы перейти к соответствующей части статьи):
- DAX функция DIVIDE
- DAX функция QUOTIENT
- DAX функция MOD
Приветствую Вас, дорогие друзья, с Вами Будуев Антон. В данной статье мы поговорим о том, как в Power BI (Power Pivot) защититься от ошибки деления на 0. А также, о том, как из общей суммы секунд вычислить соответствующее число часов, минут и секунд? А если говорить конкретнее, то разберем функции деления в DAX: DIVIDE (деление на ноль), QUOTIENT (целочисленное деление) и MOD (остаток от целочисленного деления).
Для Вашего удобства, рекомендую скачать «Справочник DAX функций для Power BI и Power Pivot» в PDF формате.
Если же в Ваших формулах имеются какие-то ошибки, проблемы, а результаты работы формул постоянно не те, что Вы ожидаете и Вам необходима помощь, то записывайтесь в бесплатный экспресс-курс «Быстрый старт в языке функций и формул DAX для Power BI и Power Pivot».
DAX функция DIVIDE в Power BI и Power Pivot
DIVIDE () — производит деление с обработкой ошибки «деление на 0». Обработка ошибки заключается в выводе альтернативного результата в случае возникновения ситуации деления на ноль.
Синтаксис:
DIVIDE (Делимое Число; Делитель; Альтернатива)
Где, альтернатива — (необязательный параметр) значение, которое нужно вывести в случае ошибки деления на ноль (0). По умолчанию выводится пустое значение BLANK ().
Пример формулы на основе DAX функции DIVIDE.
В Power BI Desktop имеется исходная таблица «Реклама», содержащая по каждой дате затраты на рекламу и прибыль, полученную от продаж с этой рекламы:
Задача — создать в Power BI меру расчета коэффициента ROI (окупаемости затрат на рекламу). Данный коэффициент рассчитывается как сумма всей прибыли деленная на сумму всех затрат.
Сумму значений мы можем рассчитать при помощи DAX функции SUM.
В итоге, формула расчета ROI будет такой:
ROI = SUM ('Реклама'[Прибыль]) / SUM ('Реклама'[Затраты])
То есть, мы сложили всю прибыль, сложили все затраты и затем разделили сумму прибыли на сумму затрат.
Вроде бы, все хорошо, но, если мы вынесем эту меру в отчеты Power BI и посмотрим ROI по дням, то в визуализации в одной из строк будет отображаться непонятное слово «Бесконечность»:
А все дело в том, что у нас произошла ошибка деления на ноль — прибыль 18000 была разделена на затраты, равные 0. И Power BI вместо этой ошибки вывела значение «Бесконечность».
Для того, чтобы исправить эту ситуацию, в формуле расчета ROI вместо обычного деления нужно использовать рассматриваемую DAX функцию DIVIDE. Она позволит нам произвести деление и обработать все ошибки, возникающие при делении на о. И вместо значения «Бесконечность» вывести то значение, которое нам нужно, например, пустое значение BLANK ().
В итоге, формула расчета ROI на основе функции DIVIDE будет такая:
ROI =
DIVIDE (
SUM ('Реклама'[Прибыль]);
SUM ('Реклама'[Затраты])
)
Где, в первом параметре функции DIVIDE мы указали сумму прибыли, которую нужно разделить, во втором параметре — сумму затрат, на которую делится сумма прибыли. Третий параметр указывать не стали, так как по умолчанию он равен функции BLANK (), что нам и нужно.
В результате, визуализация в Power BI теперь работает правильно:
Используйте функцию деления DIVIDE всегда, когда имеется хоть малейший потенциал значения нуля в делителе Вашей формулы.
DAX функция QUOTIENT в Power BI и Power Pivot
QUOTIENT () — выполняет деление чисел, входящих в параметры функции и возвращает целочисленную часть от деления.
Синтаксис:
QUOTIENT (Делимое Число; Делитель)
Пример формулы на основе DAX функции QUOTIENT.
В Power BI имеется исходная таблица «Общая Длительность Звонков», содержащая в себе информацию по общей сумме секунд всех разговоров менеджеров:
Требуется рассчитать это количество в целых часах.
Для этого, общее количество секунд нужно разделить на количество секунд в часе (3600). Но, в результате этого деления получится дробное число, а нам нужна только целая часть результата деления. В этой ситуации нам поможет функция QUOTIENT.
В итоге, формула расчета общей длительности звонков в целых часах будет такой:
Длительность В Часах =
QUOTIENT (
SUM ('ОбщаяДлительностьЗвонков'[КоличествоСекунд]);
3600
)
И в отчете Power BI по каждому менеджеру эта мера выведет количество целых часов, которые затратили менеджеры на звонки:
DAX функция MOD в Power BI и Power Pivot
MOD () — возвращает остаток от деления со знаком делителя.
Синтаксис:
MOD (Делимое Число; Делитель)
В качестве разбора формулы на основе DAX функции MOD продолжим рассматривать прошлый пример с расчетом длительности разговора менеджеров по телефону в целых часах на основе общей суммы в секундах.
Разделив общее количество секунд на 3600 при помощи QUOTIENT, мы получили целую часть от деления. Но, также, при этом делении мы можем получить и остаток от этого целочисленного деления (в нашем случае, это оставшееся количество секунд за вычетом целых часов из общего количества секунд).
И сделать это можно функцией MOD:
Остаток Секунд =
MOD (
SUM ('ОбщаяДлительностьЗвонков'[КоличествоСекунд]);
3600
)
Давайте проверим эту формулу в Power BI:
Действительно, если мы рассмотрим менеджера Петров из визуализации выше, то 16784 (общее количество секунд) — 14400 секунд (4 часа * 3600) = 2384 (остаток секунд). И функция MOD нам также вывела данное значение 2384.
Теперь, это получившееся значение (остаток секунд) можно еще раз разделить функцией QUOTIENT на 60 и мы получим целое количество минут из этого остатка секунд:
Остаток В Минутах =
QUOTIENT (
MOD (
SUM ('ОбщаяДлительностьЗвонков'[КоличествоСекунд]);
3600
);
60
)
В Power BI вычисление этой формулы будет таким:
Давайте проверим все вычисления на примере менеджера Петрова: общее количество секунд у него 16784, а 4 часа и 39 минут, это 16740 секунд (60*(4*60+39). Все правильно 16740 входит в общее количество секунд 16784.
Теперь, осталось вычислить окончательный остаток в секундах:
ОстатокВСекундах =
SUM ('ОбщаяДлительностьЗвонков'[КоличествоСекунд])
- [ДлительностьВЧасах] * 3600
- [ОстатокВМинутах] * 60
И в Power BI все это будет выглядеть так:
Напоследок, осталось навести некий «косметический дизайн» — совместим часы, минуты и секунды в единое значение «часы : минуты : секунды», для этого, воспользуемся оператором объединения в языке DAX — & и текстом с двоеточием («:»):
ДлительностьЗвонков = [ДлительностьВЧасах] & ":" & [ОстатокВМинутах] & ":" & [ОстатокВСекундах]
Итоговая визуализация, демонстрирующая совместную работу DAX функций QUOTIENT и MOD в Power BI будет такая:
Таким образом, общее количество секунд, затраченное менеджером на звонки мы превратили в соответствующее отображение в часах, минутах и секундах.
Давайте проверим все вычисления, так сказать, на калькуляторе, на примере менеджера Сидоров:
Длительность звонков = 5:9:29, то есть — 5 часов, 9 минут и 29 секунд, что равно 18569 секунд (5*3600+9*60+29). А это, в свою очередь, равно исходной сумме секунд по менеджеру Сидоров (18569 секунд).
На этом, с разбором DAX функций DIVIDE (деление на ноль «0»), QUOTIENT (целочисленное деление) и MOD (остаток от целочисленного деления) в Power BI и Power Pivot, все.
Пожалуйста, оцените статью:
- 5
- 4
- 3
- 2
- 1
(12 голосов, в среднем: 5 из 5 баллов)
![Нажмите на ссылку, чтобы записаться в экспресс-курс по DAX [Экспресс-видеокурс] Быстрый старт в языке DAX](https://biprosto.ru/wp-content/uploads/2018/08/kurs-free-5.png)
Успехов Вам, друзья!
С уважением, Будуев Антон.
Проект «BI — это просто»
Если у Вас появились какие-то вопросы по материалу данной статьи, задавайте их в комментариях ниже. Я Вам обязательно отвечу. Да и вообще, просто оставляйте там Вашу обратную связь, я буду очень рад.
Также, делитесь данной статьей со своими знакомыми в социальных сетях, возможно, этот материал кому-то будет очень полезен.
Понравился материал статьи?
Добавьте эту статью в закладки Вашего браузера, чтобы вернуться к ней еще раз. Для этого, прямо сейчас нажмите на клавиатуре комбинацию клавиш Ctrl+D
DAX-формулы или Data Analysis Expressions — выражения для анализа данных в Microsoft Power BI, в Analysis Services и Power Pivot в Excel. DAX-формулы позволяют, по аналогии с формулами Excel, выполнять вычисления и настраивать произвольную фильтрацию и представление данных в таблицах.
Язык DAX есть в следующих приложениях:
Впервые DAX-формулы появились в Excel 2010 года во внешней com-надстройке Power Pivot. С тех пор этот язык становится все более популярным, и если раньше о DAX слышали только единицы, то сейчас он широко применяется в бизнес-аналитике и проектировании моделей. Поэтому DAX-формулы вам точно пригодятся для продвинутого анализа.
В этой статье описание DAX приводится для Power Pivot в Excel и Power BI.
Строение DAX-формул
DAX-формулы очень похожи на обычные формулы Excel. Многие из них записываются одинаково, например, «сумма»-SUM и «если»-IF. Но сами вычисления работают по-разному: в отличие от обычного Excel, в языке DAX нет расчетов по ячейкам. DAX-формулы обращаются сразу к таблицам и столбцам целиком. Примерно похожий способ вычислений есть и в «обычном» Excel – с помощью формул массивов. И если вы работали с форматированными smart-таблицами, то чтобы лучше понять DAX, вспомните, как в них выглядят ссылки – название столбца в квадратных скобках.

В DAX-формулах почти также: названия таблиц обычно пишут в одинарных кавычках (или без кавычек, если имя таблицы написано латинскими буквами без пробелов и цифр в начале). Названия столбцов пишут в квадратных скобках:
'Имя таблицы'[Название столбца] или TableName[Название столбца]
Математические операторы:
& + — / * = > < () и их сочетания дают тот же эффект, что в Excel.
Логические операторы:
- && — аналог формулы И (AND)
- || — аналог ИЛИ (OR)
- IN – поиск элемента в списке
- NOT – логическое отрицание, аналог формулы НЕ.
Вычисляемые столбцы, меры и таблицы
С помощью DAX-формул в Power BI можно создавать:
- вычисляемые столбцы;
- меры;
- вычисляемые таблицы.
В Excel есть только вычисляемые столбцы и меры.
Понятия столбцов и мер – основы работы с DAX. Давайте разберемся, что это такое.
Вычисляемый столбец – это столбец, который добавляется в существующую таблицу, а DAX-формула определяет значения этого столбца.
Как и обычные столбцы в модели данных, вычисляемые столбцы можно использовать в других вычислениях. А также для создания связей между таблицами, для построения визуализаций и срезов. В сводных таблицах вычисляемые столбцы можно помещать в области фильтров, колонок, строк и значений.
Если данные в вашем файле загружаются в режиме импорта, то столбец рассчитывается и записывается в файл при загрузке и обновлении данных, увеличивая размер файла. Вычисляемые столбцы лучше использовать, когда нужен текст, дата или когда вычисление зависит от соседних колонок.
Вычисляемые столбцы создаются просто, как в Power Pivot, так и в Power BI: добавляется новый столбец, пишется «равно» и формула.

в Power Pivot

в Power BI
Чтобы обратиться к вычисляемому столбцу в других вычислениях, нужно написать имя таблицы, в которой он находится, и название самого столбца. Например, 'Таблица'[Столбец]
Меры – это динамические вычисления, результаты которых рассчитываются в зависимости от контекста. Результат вычисления меры можно увидеть в отчете, где мы задаем в каком именно контексте (в разрезе каких полей, фильтров и др.) нужно посчитать меру.
Как создать меру:
- В Excel меры записывают в окне Power Pivot в области для вычислений под таблицей: выберите ячейку, введите название меры и знак :=
Или в меню Power Pivot → Меры → Создать меру. - Чтобы создать меру в Power BI, нажмите Главная → Создать меру (или нажать правой кнопкой мышки в области полей по таблице → Создать меру).

в Power Pivot

в Power BI
При создании мер нужно обязательно использовать агрегирующие функции, например суммирования SUM. Мера не может быть создана просто как обращение к столбцу таблицы:
- Так не работает: прибыль:= 'Данные'[выручка] — 'Данные'[расходы]
+ Так работает: прибыль:= SUM('Данные'[выручка]) – SUM('Данные'[расходы])
Меры лучше создавать, когда нужны числовые вычисления, например, для промежуточных итогов, вычисления процентов, доли продукта в группе и так далее. Меры можно использовать для вычисления других мер и столбцов. При оформлении отчетов и сводных таблиц меры добавляются только в область значений.
Чтобы использовать меру в других вычислениях, ее название пишут в квадратных скобках.
Пример: МераВ = [МераА] + 100
Примечание о записи формул и разделителей:
- В Power BI формулы записывают с помощью знака равно = и разделителей-запятых.
Пример: Мера = IF( [kpi]>100, [a], [b])
В настройках Power BI есть возможность выбрать, какой именно разделитель использовать в формулах – запятую или точку с запятой.
- В Power Pivot разделителем в формулах может быть запятая «,» или точка с запятой «;» в зависимости от региональных настроек.
Вычисляемые столбцы записывают с помощью знака =
При создании меры пишут её название и знак :=
Пример: Мера:= IF( [kpi]>100; [a]; [b])
Базовые DAX-формулы
В языке DAX существует множество формул или функций, позволяющих выполнять продвинутые аналитические вычисления. Эти функции относятся к разным группам — агрегирующие, логические, математические, для работы с текстом, со временем и др. Полный список функций можно посмотреть на сайте Microsoft. Для начала разберем наиболее часто встречающиеся (на наш взгляд) формулы.
SUM суммирует числа в столбце. Её аналог в Excel – формула СУММ.
Синтаксис формулы очень простой:
SUM — это базовая формула, а всё потому что вычисления, связанные с цифрами, в DAX делаются с помощью мер. Нельзя просто так взять и обратиться к цифрам какого-то столбца напрямую. Придется это сделать с помощью какой-то агрегирующей формулы, чаще всего – с помощью SUM. Так что эта формула не только считает сумму, без нее в принципе мало какие расчёты работают )

2. BLANK
Формула BLANK возвращает пустое значение. Пустое значение в DAX – это отсутствие значения, а не привычный нам в Excel 0 (ноль) или пустая строка («»).
Записывается формула очень просто:
Никаких аргументов у нее нет.
Формулы BLANK нет в Excel, но в вычислениях с DAX она используется очень часто. Для чего нужна формула BLANK? Она помогает скрыть в отчетах ненужные значения.
3. IF
Формула IF – это логическая формула, аналог ЕСЛИ в Excel. Она проверяет условие и, если условие выполнено, возвращает одно значение, иначе – другое значение.
Синтаксис формулы:
IF(<условие>, <значение если истина>[, <значение если ложь>])
Какой же анализ данных может обойтись без логических формул? При всей важности формулы IF, используется она не так часто, как может показаться. Потому что во многих DAX-вычислениях её заменяют формулы фильтрации, о которых мы расскажем позже.

4. DIVIDE
Формула DIVIDE – формула для улучшенного деления.
Несмотря на то, что в DAX есть привычный нам оператор деления / , формула DIVIDE лучше. Она удобнее и в ней не надо делать проверку ошибки деления на ноль. Формула сама всё проверит и заменит ошибку на пустое значение.
Синтаксис формулы:
DIVIDE(<числитель>, <знаменатель> [, <альтернативный результат>])
<альтернативный результат> — это значение, которое будет выводиться, когда деление на ноль приводит к ошибке. Его указывать необязательно, по умолчанию формула возвращает пустое значение.

5. MIN и MAX
Формулы MIN и MAX – это агрегирующие формулы. Они находят минимальное и, соответственно, максимальное значение из столбца или из двух выражений (выражение должно вычислять единичное значение).
| MIN(<столбец>) MIN(<выражение1>, <выражение2>) |
MAX(<столбец>) MAX(<выражение1>, <выражение2>) |
Если вы думаете, что эти формулы нужны для поиска наименьшего или наибольшего значения показателя, то вы правы. А еще MIN и MAX часто применяются в вычислениях, связанных с датами. То есть они вам точно пригодятся – выписываем и берем на вооружение!
6. DISTINCTCOUNT
DISTINCTCOUNT – полезная формула. Она подсчитывает количество уникальных значений в столбце таблицы.
Синтаксис формулы:
С помощью этой формулы можно узнать, например, сколько покупателей сделали покупки или количество уникальных заказов, по которым велась работа. И многое другое.

7. COUNTROWS
Формула COUNTROWS считает количество всех строк в таблице. В отличие от предыдущей формулы, она считает все подряд строки, а не только уникальные значения. С помощью этой формулы можно узнать, например, число всех транзакций за период.
Синтаксис формулы:
Кстати, COUNTROWS умеет считать строки не только в простой таблице, но и в таблице, заданной каким-то выражением, например, с помощью фильтрации. Для подсчета пустых ячеек используется формула COUNTBLANK.

Давайте разберем, какие еще вычисления можно делать с помощью DAX.
Функции агрегирования
Как мы уже говорили, в DAX-формулах для обращения к данным нужно писать формулы агрегирования, такие как SUM, MAX и MIN. Также часто встречаются AVERAGE и COUNT – среднее и количество.
Кроме таких формул существуют еще другие, похожие на них с окончаниями «А» и «Х». Функции с «A» на конце обрабатывают непустые ячейки. Формулы с «X» позволяют выполнять вычисления по строкам.
| Что считать | Вычисления по таблице | Вычисления для непустых значений (A) | Вычисления для каждой строки таблицы (Х) |
| Сумма | SUM | SUMX | |
| Среднее | AVERAGE | AVERAGEA | AVERAGEX |
| Максимум | MAX | MAXA | MAXX |
| Минимум | MIN | MINA | MINX |
| Количество | COUNT | COUNTA | COUNTX |
Для чего нужны построчные вычисления в формулах с «X»? Если создать меру так:
Мера = SUM('Данные'[Цена]) * SUM('Данные'[Количество]), вычисления будут некорректные.
Необходимы вычисления по строкам:
Мера = SUMX('Данные'; [Цена] * [Количество])
Логические функции
Логические функции в DAX довольно просты для понимания. Они выполняют то же, что в «обычном» Excel. Чтобы вам было проще разобраться, собрали в таблице часто используемые логические функции.
| Формула | Что делает | Похожая формула Excel |
| IF | проверка выполнения условия | ЕСЛИ |
| AND, && | проверяет, все ли аргументы истинные | И |
| OR, || | проверяет, есть ли хотя бы один аргумент, равный TRUE | ИЛИ |
| NOT | меняет логическое значение на противоположное | НЕ |
| TRUE, FALSE | значения Истина и Ложь | ИСТИНА, ЛОЖЬ |
| IFERROR | проверяет, нет ли ошибки | ЕСЛИОШИБКА |
| SWITCH | аналог формулы IF, более удобный для множественных условий | ВЫБОР |
В пояснении нуждаются только две последние формулы — IFERROR и SWITCH.
Если формула в некоторых случаях выдает ошибку, ее можно «перехватить» с помощью IFERROR. Хотя лучше сразу проверять данные на ошибки — до выполнения расчетов.
БезОшибки = IFERROR( [Цена] * [Количество] ; BLANK() )
Формула SWITCH может выбрать 255 вариантов значений в зависимости от того, чему равна влияющая ячейка.
Например, мы можем записать формулу для времени года так:
Время года = IF( MONTH([Дата])=1; "Зима"; IF( MONTH([Дата])=2; "Зима"; IF( MONTH([Дата])=3; "Весна"; IF(MONTH([Дата])=4; "Весна"; … )
и так далее – даже если мы используем OR, легче не станет.
Со SWITCH все проще:
Время года =
SWITCH(
MONTH([Дата]);
1; "Зима";
2; "Зима";
3; "Весна";
4; "Весна"; … )
и так далее – уже проще и понятнее.
Математические функции
Чтобы хорошо разобраться в математических формулах, вспомните, какие именно из них вы чаще всего применяете в вычислениях и найдите аналогичные в DAX. Про формулы SUM и DIVIDE мы уже писали, а далее в таблице собраны другие популярные формулы.
| Формула | Что делает | Похожая формула Excel |
| ABS | находит модуль числа | ABS |
| SIGN | определяет знак числа | ЗНАК |
| POWER | возведение в степень | СТЕПЕНЬ |
| SQRT | находит квадратный корень | КОРЕНЬ |
| QUOTIENT | возвращает только целую часть деления | ОТБР |
| RANDBETWEEN | возвращает случайное число в диапазоне между двумя числами | СЛУЧМЕЖДУ |
| ROUND | округление до заданного числа десятичных разрядов | ОКРУГЛ |
| ROUNDUP | округление в большую сторону | ОКРУГЛВВЕРХ |
| ROUNDDOWN | округление в меньшую сторону | ОКРУГЛВНИЗ |
Текстовые функции
Текстовые функции в DAX основаны на аналогичным списке функций в Excel. Наиболее часто используемые функции собраны в таблице.
| Формула | Что делает | Похожая формула Excel |
| CONCATENATE, CONCATENATEX и оператор & | объединяет текстовые строки в одну, оператор & используется для объединения строк текста | СЦЕПИТЬ, ОБЪЕДИНИТЬ и & |
| TRIM | удаляет лишние пробелы | СЖПРОБЕЛЫ |
| LOWER и UPPER | преобразует все буквы в строке в строчные / прописные | СТРОЧН и ПРОПИСН |
| LEFT и RIGHT | возвращает указанное количество символов с начала (конца) строки | ЛЕВСИМВ и ПРАВСИМВ |
| LEN | возвращает число символов в строке | ДЛСТР |
| FIND и SEARCH | возвращает номер начальной позиции искомого текста в строке (с учетом или без учета регистра) | НАЙТИ и ПОИСК |
| MID | возвращает строку из текста по начальной позиции и длине | ПСТР |
| FORMAT | преобразует значение в текст в соответствии с указанным форматом | ТЕКСТ |
Функции для работы с датами
В DAX часто встречаются вычисления, связанные с датами. Поэтому там много формул, позволяющих такие расчеты выполнять.
| Формула | Что делает | Похожая формула Excel |
| TODAY | определяет сегодняшнюю дату | СЕГОДНЯ |
| DATE | возвращает заданную дату | ДАТА |
| DAY, MONTH, YEAR | вычисляет день, месяц, год для заданной даты | ДЕНЬ, МЕСЯЦ, ГОД |
| WEEKDAY | возвращает номер дня недели, от 1 до 7 | ДЕНЬНЕД |
| WEEKNUM | определяет номер недели в году | НОМНЕДЕЛИ |
| EDATE | находит дату через указанное число месяцев от заданной даты | ДАТАМЕС |
| EOMONTH | находит дату последнего дня месяца до или после указанного числа месяцев | КОНМЕСЯЦА |
Функции фильтрации
А еще в DAX есть формулы фильтров, аналога которых в «обычном» Excel нет и быть не может. Потому что такие формулы позволяют ссылаться не просто на столбец, а целиком на таблицу. Формулы фильтрации можно подставлять в меры и тогда они будут выдавать «виртуальные» таблицы с заданными параметрами. Такие таблицы не дают видимого результата и используются как промежуточные функции внутри вычисления. Примером таких функций являются SUMMARIZE, ADDCOLUMNS и более часто используемые формулы FILTER, ALL.
В определениях DAX функция CALCULATE относится к функциям фильтрации. CALCULATE работает по аналогии с формулой СУММЕСЛИМН при указании в этой формуле суммы и условия отбора – фильтра:
продажи-2020 = CALCULATE( [факт]; 'Календарь'[Год] = 2020 )
Самыми яркими представителями функций фильтрации являются FILTER и ALL:
- Функция FILTER создает отфильтрованную таблицу. Другими словами, с помощью этой формулы можно извлечь список, соответствующий определенному критерию.
- Функция ALL снимает фильтры, примененные к таблице. Она используется, например, чтобы посчитать долю продаж товара:
Доля товара = DIVIDE( [выручка]; CALCULATE( [выручка]; ALL(
'Товары') )
Кроме функций, перечисленных выше, в DAX существуют другие – функции связей, обработки таблиц, информационные, статистические, финансовые, функции операций со временем и т.д. Как видите, язык DAX позволяет выполнять самые разные вычисления. Примеры таких вычислений можно посмотреть в следующих статьях.
DIVIDE DAX Function (Math and Trig)
Safe Divide function with ability to handle divide by zero case.
Syntax
DIVIDE ( <Numerator>, <Denominator> [, <AlternateResult>] )
| Parameter | Attributes | Description |
|---|---|---|
| Numerator |
Numerator. |
|
| Denominator |
Denominator. |
|
| AlternateResult | Optional |
Optional. The alternate result to return when dividing by zero. |
Return values
Scalar A single decimal value.
Result of the division between Numerator and Denominator, or AlternateResult in case there is a division by zero.
» 2 related articles
» 2 related functions
Examples
-- DIVIDE performs safe division protecting from division by
-- zero. In case of zero denominator, it returns its third
-- argument that defaults to a blank.
DEFINE
MEASURE Sales[Unprotected Growth %] =
VAR CY = [Sales Amount]
VAR PY = CALCULATE ( [Sales Amount], SAMEPERIODLASTYEAR( 'Date'[Date] ) )
RETURN (CY - PY) / PY
MEASURE Sales[Protected Growth %] =
VAR CY = [Sales Amount]
VAR PY = CALCULATE ( [Sales Amount], SAMEPERIODLASTYEAR( 'Date'[Date] ) )
RETURN DIVIDE ( CY - PY, PY, BLANK () )
EVALUATE
SUMMARIZECOLUMNS (
'Date'[Calendar Year],
"Unprotected Growth %", [Unprotected Growth %],
"Protected Growth %", [Protected Growth %]
)
| Calendar Year | Unprotected Growth % | Protected Growth % |
|---|---|---|
| 2007-01-01 | Infinity | (Blank) |
| 2008-01-01 | -0.12222543928588246 | -12.22% |
| 2009-01-01 | -0.057795348753533114 | -5.78% |
| 2010-01-01 | -1 | -100.00% |
Related articles
Learn more about DIVIDE in the following articles:
-
DIVIDE Performance
The DIVIDE function in DAX is usually faster to avoid division-by-zero errors than the simple division operator. However, there are exceptions to this rule, described in this article through a simple performance analysis. » Read more
-
From SQL to DAX: Implementing NULLIF and COALESCE in DAX
This article describes how to implement a syntax equivalent to the T-SQL function NULLIF and the ANSI SQL function COALESCE, in DAX. » Read more
Related functions
Other related functions are:
- QUOTIENT
- IFERROR

Last update: Jan 24, 2023 » Contribute » Show contributors
Contributors: Alberto Ferrari, Marco Russo, Kenneth Barber,
Microsoft documentation: https://docs.microsoft.com/en-us/dax/divide-function-dax
2018-2023 © SQLBI. All rights are reserved. Information coming from Microsoft documentation is property of Microsoft Corp. » Contact us » Privacy Policy & Cookies
В языке для анализа данных DAX множество функций. В этой статье мы рассмотрим самые частоиспользуемые из них.
Набор данных
Тренироваться мы будем на простой импортированной в PowerBI Google-таблице, в которой содержится информация о продажах интернет-магазина: приобретенные товары, сумма чека, идентификатор покупателя. В PowerBI Desktop эту таблицу назовем «Заказы».
| Товары | Сумма чека | ID Покупателя | Дата |
| Компьютер | 30000 | 1 | 01.03.18 |
| Компьютер, телевизор | 50000 | 2 | 01.03.18 |
| Планшет | 12000 | 3 | 02.03.18 |
| Смартфон | 18000 | 4 | 03.03.18 |
| Ноутбук | 70000 | 5 | 03.03.18 |
| Мышь | 1000 | 1 | 04.03.18 |
| Планшет | 14000 | 2 | 05.03.18 |
| Смарфон, компьютер | 48000 | 7 | 06.03.18 |
| Смартфон | 18000 | 6 | 06.03.18 |
| Компьютер | 30000 | 1 | 06.03.18 |
Функция SUM в DAX
Для начала, давайте посчитаем, какую выручку принес нам интернет-магазин. Для этого нам необходимо просуммировать все значения в столбце «Сумма чека».
В этом нам поможет функция SUM с простым синтаксисом:
SUM()
Всё, что нужно для расчета выручки — создать DAX-формулу с указанием столбца «Сумма чека»:
Выручка = SUM('Заказы'[Сумма чека])
Обратите внимание, что для работы функции необходимо, чтобы у столбца был числовой тип.
Функции COUNT и DISTINCTCOUNT
Предназначение данных функций — считать количество строк, их синтаксис так же прост, как и у функции SUM:
COUNT()
DISTINCTCOUNT()
Для начала, давайте посчитаем кол-во заказов в нашей таблице. Поскольку одному заказу соответстует одна строчка в нашей таблице, для вычисления количества заказов необходимо просто посчитать кол-во строк по любому из столбцов:
Заказы = COUNT('Заказы'[Товары])
В отличие от COUNT, DISTINCTCOUNT считает только количество строк с уникальными значениями выбранного столбца. С помощью этой функции мы сможем посчитать уникальное количество наших клиентов. В данном случае нам нужно выбрать уже не любой столбец, а исключительно столбец «ID покупателя»:
Уникальные клиенты = DISTINCTCOUNT('Заказы'[ID Покупателя])
Функция DIVIDE
Функция DIVIDE — это замена стандартной операции деления в PowerBI. Я крайне рекомендую использовать ее в своих BI-моделях, поскольку в отличие от стандартной операции деления при использовании DIVIDE не возникает ошибки в случае деления на ноль.
Синтаксис этой функции уже немного сложнее:
DIVIDE(<Числитель>, <Знаменатель> [,<альтерн. результат>])
За значение созданной меры в случае деления на ноль отвечает параметр «альтернативный результат». Это необязательный параметр, по умолчанию он равен BLANK(), которая возвращает пустой результат.
Давайте вычислим средний чек нашего интернет-магазина, для этого нам нужно разделить выручку на кол-во заказов. Посколько обе эти меры у нас уже созданы, формула будет выглядеть следующим образом:
Средний чек = DIVIDE([Выручка];[Заказы])]
Если вам не нужны меры «Выручка» и «Заказы», вы можете использовать функции SUM и COUNT прямо внутри функции DIVIDE:
Средний чек = DIVIDE(SUM('Заказы'[Сумма чека]);COUNT('Заказы'[Товары]))
Это продолжение перевода книги Роб Колли. Формулы DAX для Power Pivot. Главы не являются независимыми, поэтому рекомендую читать последовательно.
Предыдущая глава Содержание Следующая глава
Добавим условную логику в наши DAX-формулы. Рассмотрим рост по сравнению с предыдущим годом (Year-Over-Year, YOY) из предыдущей главы:
|
[Pct Sales Growth YOY] = ([Total Sales] — [Total Sales DATEADD 1 Year Back]) / [Total Sales DATEADD 1 Year Back] |
Значение за 2001 год возвращает ошибку, потому что продажи в прошлом году [Total Sales DATEADD 1 Year Back] равны 0. Это действительно ошибка деления на 0.

Рис. 15.1. Ошибка #Число! для 2001 года: деление на ноль
Скачать заметку в формате Word или pdf, примеры в формате Excel
Ситуацию легко исправить с помощью интуитивно понятной функции IF():
|
[Pct Sales Growth YOY] = IF( [Total Sales DATEADD 1 Year Back]<>0; ([Total Sales] — [Total Sales DATEADD 1 Year Back]) / [Total Sales DATEADD 1 Year Back]; 0 ) |

Рис. 15.2. Теперь мера возвращает 0% вместо ошибки
Функция BLANK()
Мы можем еще улучшить отображение. 0% означает, что у нас был нулевой рост, тогда как на самом деле этот расчет вообще не имеет смысла для 2001 года. Поэтому вместо 0 мы можем вернуть функцию BLANK():
|
[Pct Sales Growth YOY] = IF( [Total Sales DATEADD 1 Year Back] = 0; BLANK(); ([Total Sales] — [Total Sales DATEADD 1 Year Back]) / [Total Sales DATEADD 1 Year Back] ) |

Рис. 15.3. Теперь 2001 год просто не отображается
Это очень полезный трюк. Запомните такое использование функции BLANK()!
Если мы добавим в сводную таблицу второе поле Значений, которое для 2001 года возвращает значение, отличное от нуля, строка за 2001 год вновь проявится:

Рис. 15.4. 2001-й год будет отображаться, если хотя бы одна мера возвращает непустой результат
И наоборот, если вам не нравится отсутствие значений в каком-либо поле, вы можете настроить сводную, и отражать там нечто иное. Для этого активируйте сводную таблицу, перейдите на вкладку Анализ, и в левой части ленты кликните Параметры (или кликните правой кнопкой мыши на сводной и выберите Параметры сводной таблицы). Установите значения, которые следует отражать вместо ошибок и пропусков:

Рис. 15.5. Настройка сводной таблицы для отражения ошибочных и пустых значений
Функция DIVIDE()
DIVIDE(<числитель>; <знаменатель> [; <значение, если знаменатель равен нулю>])
DIVIDE() – безопасное деление; третий аргумент является необязательным, и по умолчанию возвращает BLANK(), что удобно в большинстве случаев. Можно записать:
|
[Pct Sales Growth YOY using DIVIDE] = DIVIDE( [Total Sales] — [Total Sales DATEADD 1 Year Back]; [Total Sales DATEADD 1 Year Back] ) |
Элегантно, не правда ли?
Шаблон IF…THEN…ELSE полезен не только при делении, и пригодится во многих иных ситуациях. Для деления же мы рекомендуем использовать DIVIDE(), и забыть про проблему с нулевым знаменателем.
Шаблон IF(<test>; <DAX выражение>; BLANK()) мы также рекомендуем запомнить.
Функция ISBLANK
В Excel есть функция ЕПУСТО(). Она возвращает значение ИСТИНА, если ячейка пуста, и значение ЛОЖЬ в иных ситуациях. Функция нужна, когда мы хотим отличить пустую ячейку от ячейки, содержащей пробелы, или пустой текстовой строки ="", или строки с формулой, возвращающей пустое/нулевое значение.
Если обратиться к примеру выше, функция ISBLANK() может быть полезна, если мы хотим отличить ситуацию, когда [Total Sales DATEADD 1 Year Back] возвращает законный 0 (то есть, строки продаж имелись, но сумма столбца SalesAmount = 0; редко, но возможно). Поэтому большую часть времени мы просто проверяем "=0". Но когда вы хотите отличить 0 от BLANK(), ISBLANK() – это то, что вам нужно.
HASONEVALUE()
Допустим вы хотите создать меру для определения процентного вклада отдельных строк в категорию:
|
[Subcategory pct of Category Sales] = [Total Sales] / CALCULATE( [Total Sales]; ALL(Products[SubCategory]) ) |
После того, как мы поместим меру в сводную таблицу вместе с [Total Sales]…

Рис. 15.6. Продажи и их доля в категории
… увидим бесполезные 100,0% в строках подытогов. Чтобы подавить их можно использовать функцию HASONEVALUE(). Она проверяет, содержит ли контекст фильтра одно наименование (и возвращает ИСТИНА) или несколько, т.е., относится к промежуточным/общим итогам (и возвращает ЛОЖЬ). Вставим такую проверку в нашу меру:
|
[Subcategory pct of Category Sales] = IF( HASONEVALUE(Products[SubCategory]); [Total Sales] / CALCULATE( [Total Sales]; ALL(Products[SubCategory]) ); BLANK () ) |

Рис. 15.7. Промежуточные и общие итоги для меры [Subcat pst of Cat Sales] подавлены
HASONEVALUE() эквивалентно IF(COUNTROWS(VALUES())=1.
Мы могли бы отключить промежуточные и/или общие итоги на вкладке Конструктор на ленте. Но это также отключит подытоги/итоги для столбца [Total Sales]. А мы хотели сделать это только для столбца [Subcat pct of Cat Sales].
IF() на основе полей сводной таблицы
Выше мы использовали IF() для сравнения со значением меры. Но что, если мы хотим проверить, где мы «находимся» с точки зрения контекста фильтра? Например, мы хотим вычислить что-то немного по-другому для конкретной страны? Добавим в модель таблицу подстановки SalesTerritory. Она содержит столбец Country, который мы поместим в строки сводной таблицы для меры Продажи родителям [Sales to Parents]
Sales to Parents = CALCULATE([Total Sales]; Customers[NumberChildrenAtHome] > 0)

Рис. 15.8. Сумма для Канады не вызывает доверия
Допустим, у нас есть сомнения в данных по столбцу [NumberOfChildren]. Возможно, то, как мы собираем данные в Канаде, делает это число ненадежным. А этот столбец лежит в основе расчета меры [Sales to Parents]. Поэтому для Канады, и только для Канады, мы хотим заменить эту меру другой мерой, [Sales to Married Couples]. Поэтому мы введем новую меру:
|
[Sales to Parents Adj for Canada] = IF( HASONEVALUE(SalesTerritory[Country]); IF( VALUES(SalesTerritory[Country]) = «Canada»; [Sales to Married Couples]; [Sales to Parents] ); BLANK() ) |
Функция VALUES() возвращает контекст фильтра, установленный в сводной таблице. Если вы находить в обычной ячейке, он возвращает одно значение. Если вы в строке подытогов/итогов, он возвращает несколько значений:
![Рис. 15.9. Формула VALUES(SalesTerritory[Country]) вернет для (а) значение Canada Ris. 15.9. Formula VALUESSalesTerritoryCountry vernet dlya a znachenie Canada](https://baguzin.ru/wp/wp-content/uploads/2019/01/Ris.-15.9.-Formula-VALUESSalesTerritoryCountry-vernet-dlya-a-znachenie-Canada.jpg)
Рис. 15.9. Формула VALUES(SalesTerritory[Country]) вернет для (а) значение Canada; для (b) – Australia, Canada, France, Germany, United Kingdom, United States
Мы не можем непосредственно проверить условие IF(SalesTerritory[Country]). Оно нарушает правило для мер – не использовать голые столбцы в качестве аргументов мер. Ранее мы «заворачивали» столбец в какую-нибудь арифметическую функцию. Но, поскольку Country – это текстовая строка, нам нужно использовать какую-то иную функцию. Вот почему мы выбрали VALUES(). В итоге условие проверки выглядит так: IF(VALUES(SalesTerritory[Country])="Canada".
Если мы выполним тест IF(VALUES(…)) ="Canada" в ячейке, которая вернет более одного значения, мы получим ошибку. Поэтому нам нужно предварительно проверить, что мы находимся в ячейке с единственным значением страны. Для этого мы используем конструкцию IF(HASONEVALUE(SalesTerritory[Country])
Вот что мы в итоге получим:

Рис. 15.10. Две меры отличается только для Канады
Мы также убрали итоговое значение из столбца Sales to Parents Adj for Canada. Оно было бы не корректным, так как значение для Канады мы взяли из другого столбца.
Значение, возвращаемое VALUES(), не зависит от того, выводится ли поле в сводную таблицу
Посмотрите на сводную таблицу, которая показывает количество продуктов по категориям и цветовой гамме:
![Рис. 15.11. Что именно возвращает мера VALUES(Products[Color]) для выделенной ячейки Ris. 15.11. CHto imenno vozvrashhaet mera VALUESProductsColor dlya vydelennoj yachejki](https://baguzin.ru/wp/wp-content/uploads/2019/01/Ris.-15.11.-CHto-imenno-vozvrashhaet-mera-VALUESProductsColor-dlya-vydelennoj-yachejki.jpg)
Рис. 15.11. Что именно возвращает мера VALUES(Products[Color]) для выделенной ячейки?
Для выделенной на рис. 15.11 ячейки, мера VALUES(Products[Color]) возвращает количество продуктов всех цветов: {"Black", "Blue", "Red", "Silver", "Yellow"}. Обратите внимание, что «Grey» и «NA» не возвращаются для этой ячейки. Но эти два цвета возвращаются для категории Accessories. Это связано с тем, что Category и Color (поля в строках) являются столбцами таблицы Products, что означает, что фильтр категорий влияет на допустимость цвета. Категория велосипеды "Bikes" фильтрует таблицу Products, а велосипеды в цветовой гамме "Grey" или "NA" отсутствуют.
Если мы удалим поле Color из сводной таблицы, что вернет мера VALUES(Products[Color])?

Рис. 15.12. Итоговые значения по категориям не изменятся
Независимо от того, было ли поле Color выведено в сводную или нет, выделенная нами ячейка С10 на рис. 15.11 не имела никаких фильтров, связанных с цветом.
VALUES() может возвращать уникальные значения
Мы использовали меру [Product Count] для определения числа продуктов в категории (всего или в той или иной цветовой гамме). Например (см. рис. 15.11), имеется 35 продуктов в категории Accessories, принадлежащих к 6 различным цветам. Для подсчета числа цветов в категории используем меру
[Color Values] = COUNTROWS(VALUES(Products[Color]))
![Рис. 15.13. Мера [Color Values] возвращает только уникальные значения для цвета Ris. 15.13. Mera Color Values vozvrashhaet tolko unikalnye znacheniya dlya tsveta](https://baguzin.ru/wp/wp-content/uploads/2019/01/Ris.-15.13.-Mera-Color-Values-vozvrashhaet-tolko-unikalnye-znacheniya-dlya-tsveta.jpg)
Рис. 15.13. Мера [Color Values] возвращает только уникальные значения для цвета
Характерно, что итоговая строка на рис. 15.13 возвращает значение 10, а не сумму цветов по категориям. Если убрать фильтр со столбца Category, разных цветов у всех продуктов будет 10.
SWITCH()
Если мы хотим проверить несколько условий, вложенные IF() – один из способов решения, но функция SWITCH() намного проще и прозрачнее. В модели данных мы добавили вычисляемый столбец, чтобы увидеть работу функции SWITCH() в действии, но ее можно использовать и в мерах (рис. 15.14).

Рис. 15.14. Функции SWITCH() определяет континент на основе страны
Вот как работает SWITCH(). Первый аргумент – проверяемое выражение. Начиная со второго аргументы SWITCH() работают парами: четный аргумент сравнивается с проверяемым выражением и в случае совпадения возвращает следующий за ним нечетный аргумент. Например, если проверяемое значение "United States", то возвращается "North America", если "France" – возвращается "Europe". Если вы заканчиваете SWITCH() "четным" аргументом, он рассматривается как "ELSE" и работает без пары. Т.е., если среди четных аргументов {"United States"; "Canada"; …; "United Kingdom"}, не найдется проверяемое выражение, то функция SWITCH() вернет "Rest of the World".
SWITCH TRUE()
Функция SWITCH() может быть еще более универсальной, когда в качестве первого аргумента используется TRUE(). Далее можно указать условия для сопоставления, а не точные значения. Например, добавим еще один вычисляемый столбец в таблицу Products для указания диапазона цен прайс-листа:

Рис. 15.15. Конструкция SWITCH TRUE() позволяет указать условия для проверки
Здесь, как и раньше, начиная со второго, аргументы SWITCH() работают парами. Однако вместо соответствия определенному значению они оценивают условие; если оно истинно, то выбирается парное значение. Например, если значение [List Price] < 100, то возвращается "$". Если вы заканчиваете SWITCH() "четным" аргументом, это рассматривается как "ELSE". В этом случае "$$$$" возвращается, если ни одно из условий не совпадает. Обратите внимание, что важен порядок условий: если первое из них выполняется, дальнейших проверок не будет. Поэтому, если вы указали [List Price] < 1000 в качестве первого условия, оно будет верно, и для изделия по цене $90, и $400.
Для ускорения работы модели данных лучше создавать вычисляемые столбцы за пределами Power Pivot (например, в Excel, базе данных, или с помощью Power Query), а затем импортировать их как часть исходной таблицы.
Постоянно выскакивала проблема с делением на ноль. Как от этого избавиться красиво?
Что испробовано:
— Сначала в методе checkDivisionByZero была добавлена проверка на
textBuffer.find(‘/(((0)+(0))-((0)+(0)))’), но это оказалось как мертвому припарка, потому что тут де выскочило сообщение типа
«((a+b)/((a+b) — (a+b)) — деление на ноль.
— Тогда в метод calculateColumnCalcListColumn был добавлен код
X++:
ZeroDivider = false; dividerpos = strscan(str2, '/',1,999); divider = substr(str2,dividerpos+1,strlen(str2)-dividerpos-1); if (dividerpos != 0 && divider != '') { bufdevider = strfmt(buf, divider); if (compiler.compile(bufdevider) && (! this.checkDivisionByZero(bufdevider))) { //BP Deviation documented tmpAmount = runbuf(bufdevider); } else { // info(strfmt("@SYS85024", str2, _ledgerBalColumnsDim.Column, idx_calc)); tmpAmount = 0; } if (tmpAmount == 0) ZeroDivider = true; } //if (compiler.compile(buf2) && (! this.checkDivisionByZero(buf2))) if (compiler.compile(buf2) && (! this.checkDivisionByZero(buf2)) && !ZeroDivider) { ...
и далее по тексту, но ведь если разобраться, то может быть вложенное деление на ноль…
Как же это сделать красиво, может кто нибудь уже боролся с этим?
__________________
Может быть выйдет, а может не-е-е-ет…
Новая песня вместо штиблет..
DAX DIVIDE Function
DIVIDE function is a power bi DAX math and trig functions that performs the division and returns alternate result or BLANK() on division by 0.
It returns a decimal number.
SYNTAX
DIVIDE(<numerator>, <denominator> [,<alternateresult>])
numerator The dividend or number to divide.
denominator The divisor or number to divide by.
alternateresult It is an optional, returned when division by zero error occurred.
By default it returns blank().
Lets look at an example of using DIVIDE function in Power Bi.
Here we have a sample dataset of student score card.
Note that, You can see MaxMarks is 0 for studid 101 , and 104 in Subject English and Math respectively.
Which are taken purposely to see the DIVIDE function ability to handle the divide by zero error, and return alternate value if it is given else blank.

StudId Subject Marks Obtain MaxMarks
| 101 | Math | 79 | 100 |
| 101 | Science | 80 | 100 |
| 101 | English | 92 | 0 |
| 102 | Math | 83 | 100 |
| 102 | Science | 74 | 100 |
| 102 | English | 56 | 100 |
| 103 | Math | 69 | 100 |
| 103 | Science | 49 | 100 |
| 103 | English | 94 | 100 |
| 104 | Math | 75 | 0 |
| 104 | Science | 87 | 100 |
| 104 | English | 91 | 100 |
Lets say, you want to calculate the percentage achieved by student in each subject.
To calculate the percentage, first you need to divide Marks obtain (dividend) in subject by max marks (divisor) then multiple by the result by 100.
Lets use the DIVIDE function DAX for the division as given below.
Subject % = DIVIDE ( SUM ( StudentScoreCard[Marks Obtain] ), SUM ( StudentScoreCard[MaxMarks] ) ) * 100

After committing, the above DAX Subject %, Lets drag it into table visual as shown below.

If you want to replace blank value with zero, then you can modify above DAX and provide an alternate value, when divide by zero error occurred.
Subject % = DIVIDE ( SUM ( StudentScoreCard[Marks Obtain] ), SUM ( StudentScoreCard[MaxMarks] ) ,0 ) * 100

As you can see, Blank value is replaced with an alternate value 0.

| SQL Basics Tutorial | SQL Advance Tutorial | SSRS | Interview Q & A |
| SQL Create table | SQL Server Stored Procedure | Create a New SSRS Project | List Of SQL Server basics to Advance Level Interview Q & A |
| SQL ALTER TABLE | SQL Server Merge | Create a Shared Data Source in SSRS | SQL Server Question & Answer Quiz |
| SQL Drop | SQL Server Pivot | Create a SSRS Tabular Report / Detail Report | |
| ….. More | …. More | ….More | |
| Power BI Tutorial | Azure Tutorial | Python Tutorial | SQL Server Tips & Tricks |
| Download and Install Power BI Desktop | Create an Azure storage account | Learn Python & ML Step by step | Enable Dark theme in SQL Server Management studio |
| Connect Power BI to SQL Server | Upload files to Azure storage container | SQL Server Template Explorer | |
| Create Report ToolTip Pages in Power BI | Create Azure SQL Database Server | Displaying line numbers in Query Editor Window | |
| ….More | ….More | ….More |
7,337 total views, 3 views today

Мы уверены, что многие читатели нашего блога хорошо разбираются в вычислениях, которые мы приводим в демонстрационных отчетах. Однако новые пользователи Power BI зачастую не знают, что такое DAX и как его можно использовать для расчета необходимых показателей. Поэтому этой статьей мы хотим начать экскурс в основы языка DAX, и в качестве примера мы возьмем отчет по посещаемости блога, который был предоставлен нам командой Mello и который мы уже рассматривали ранее.
Итак, сначала, как полагается, немного теории.
Data Analysis Expressions, сокращенно DAX (и не спрашивайте почему именно так)) — это язык запросов для Power Pivot, Power BI Desktop и SQL Server Analysis Services (SSAS). Это некий набор функций, операторов и констант, которые можно использовать в формуле или выражении, чтобы подсчитывать и возвращать одно или несколько значений. Говоря проще, DAX помогает создавать новую информацию из данных, уже имеющихся в модели.
Этот язык запросов (а это именно язык) включает библиотеку из более чем 200 функций, операторов и конструкций, что обеспечивает огромную гибкость для выполнения различных вычислений.
Идем дальше и разберем, что же такое мера и вычисляемый столбец и чем они все таки отличаются друг от друга.
Мера является базовым понятием в DAX и представляет собой выражение, которое позволяет рассчитать необходимый показатель на основании данных из модели. Пример использования мер, это расчет среднего, суммы, количества уникальных записей и пр.
Вычисляемый столбец не менее важен и также позволяет рассчитать показатели, но подсчет производится для каждой строки таблицы отдельно и результат сохраняется в отдельное поле (новый столбец таблицы). После создания подобного вычисляемого столбца его можно использовать наравне с остальными столбцами модели. Пример использования вычисляемого столбца — создание некоего столбца с ключами (уникальными идентификаторами записей, для связей с другими таблицами).
Продолжим разбираться в основных отличиях между мерами и вычисляемыми столбцами и посмотрим на них с точки зрения ресурсоемкости будущего отчета.
Меры, в отличие от столбцов, вычисляются только во время использования визуализации, в то время как значения нового столбца вычисляются моментально после его создания. Также вычисляемый столбец сохраняется вместе со всей моделью и его значения рассчитываются во время загрузки данных в модель, в то время как для меры хранится только формула, по которой она вычисляется.
И главное, что необходимо всегда помнить — это то, что вычисляемые столбцы используются для формирования значений в контексте каждой отдельной строки, а меры агрегируют эти значения для всей таблицы.
Здесь и далее примем следующие обозначения:
- ‘Таблица’
- ‘Таблица'[Столбец]
- [Мера]
Теперь можно смело переходить к практике. Разберем как задать меру и вычисляемый столбец, какие они бывают и что умеют делать.
Начнем анализ с разбора одной из простейших мер. Для удобства чтения будем обозначать меры через знак :=, в то время как для столбцов будем использовать стандартный знак равенства.
Ранее мы уже писали о том, что все показатели, существующие в таблицах, мы рекомендуем «оборачивать» мерами, что имеет ряд преимуществ. Подобным подходом мы воспользовались и при сборе модели, которая лежит в основе рассматриваемого в статье отчета. В результате чего в ней довольно много мер, выполняющих простые вычисления, с одной из которых мы и начнем наше знакомство с DAX:
Просмотры страниц := SUM ( 'Просмотры страниц'[Количество просмотров] )
Давайте рассмотрим из чего состоит приведенное выше выражение. С левой стороны от знака равенства указывается название меры, в данном случае это [Просмотры страниц]. Напомним, что названия необходимо давать максимально понятные, чтобы они передавали суть того значения, которое получится в результате вычисления. Это значительно облегчит дальнейшую работу с отчетом и сэкономит массу времени на выяснения что же та или иная мера считает.
Но и увлекаться не стоит: сильно длинные названия давать не советуем, так как с ними потом будет не очень удобно работать. Если же это какая-то специфическая мера и необходимо пояснить что она вычисляет, то лучше добавить описание. Для этого кликаем правой кнопкой мыши на нужной нам мере в списке полей и выбираем пункт:

В открывшемся окне Свойство полей в поле Описание смело пишем все, что будущим пользователям отчета нужно знать о мере:

Если после этих манипуляций в списке Полей просто навести мышкой на нужную меру, мы увидим уже не только ее полное название, а и заданное нами описание:

С правой стороны знака равенства мы видим функцию SUM, которая предназначена для суммирования всех значений в столбце, который в свою очередь передается в качестве параметра и в данном случае это ‘Просмотры страниц'[Количество просмотров]. Следует отметить, что столбец [Количество просмотров] в данном случае необходимо указывать вместе с названием таблицы ‘Просмотры страниц’, в которой он находится.
Аналогичным образом, оборачивая столбцы с числовыми значениями, мы получаем и другие меры: [Входы], [Выходы], [Длительность просмотра страницы], [Длительность сеанса] и пр.
Но у нас в отчете есть и другие меры, будем их рассматривать по степени возрастания сложности их синтаксиса. Итак, есть меры, которые представляют собой относительные величины — долю чего либо.
Например:
Процент входов := DIVIDE ( [Входы]; [Просмотры страниц]; 0 )
Слева от знака равенства снова название меры (мы больше к этому не будем возвращаться), а справа функция с тремя аргументами:
DIVIDE ( Числитель; Знаменатель; Альтернативный результат )
Все просто: чтоб получить процент входов из числа просмотров, мы делим [Входы] на [Просмотры страницы], и возвращаем ноль, в случае если результат такого деления возвращает ошибку.
Стоит отметить, что [Входы] и [Просмотры страниц], это меры, в которые мы выше оборачивали данные модели.
Аналогичный синтаксис имеют такие меры отчета как [Процент выходов], [Средняя длительность просмотра страницы], [Страниц на сеанс] и пр. Все их можно найти в разделе Поля в так называемых таблицах мер, у нас в отчете их две ‘Просмотры страницы’ и ‘Сеансы’.

Рассмотрим еще одну не сложную, но полезную функцию, используемую в расчете меры:
Пользователи := DISTINCTCOUNT ( 'Сеансы'[Идентификатор пользователя] )
Эта мера возвращает только уникальные записи из таблицы ‘Сеансы’, а именно из столбца [Идентификатор пользователя]. Почему именно так? Потому что, один пользователь может просматривать несколько страниц и при том не один раз. В таблице в этом случае будет несколько идентификаторов пользователя (т.е. сколько просмотров — столько и идентификаторов). А нам важно узнать сколько уникальных пользователей просмотрело страницу. Поэтому мы считаем сколько уникальных идентификаторов (уникальных пользователей) есть в нашей таблице с данными.
Теперь перейдем к более сложным расчетам и рассмотрим такую меру:
Средний процент прокрутки страницы := AVERAGEX ( CALCULATETABLE ( GROUPBY ( 'События'; 'События'[Идентификатор просмотра]; "Процент прокрутки"; MAXX ( CURRENTGROUP (); VALUE ( 'События'[Ярлык события] ) ) ); FILTER ( 'События'; 'События'[Категория событий] = "Max Scroll" ) ); [Процент прокрутки] ) / 100
Начнем разбираться максимально подробно.
Средний процент прокрутки страницы – это показатель, который говорит нам о том, на сколько процентов пользователи при посещении страницы прокручивают ее.
Теперь разберемся, как он считается.
У нас есть нужная таблица со всеми необходимыми нам исходными данными, это таблица ‘События’, где содержится вся информация по всем событиям, произошедшим на странице. Более подробно с содержанием этой таблицы Вы можете ознакомиться в нашей статьей «Пример построения модели на данных Google Analytics».
Но таблица ‘События’ содержит также и много ненужной нам сейчас информации. Так например, в таблице собраны вместе все категории событий, в то время как нам нужна только категория Max Scroll. Можно увидеть, выбрав эту категорию, что ярлык события в этом случае будет как раз равен проценту прокрутки страницы для каждого просмотра (Идентификатор просмотра).
Осталось понять, как посчитать среднее

Из таблицы выше видно, что в исходных данных каждому Идентификатору просмотра может соответствовать несколько значений Ярлыка событий. Соответственно сколько событий прокрутки страницы было, столько у нас будет и Ярлыков для заданного просмотра. Все логично.
Для того чтоб вычислить средний процент прокрутки, нам нужно будет построить сводную таблицу по таблице ‘События’, в которую мы соберем все максимальные значения процента прокрутки по каждому отдельному событию:
GROUPBY ( 'События'; 'События'[Идентификатор просмотра]; "Процент прокрутки"; MAXX ( CURRENTGROUP (); VALUE ( 'События'[Ярлык события] ) ) )
В нашем случае получается что мы из исходной таблицы ‘События’, берем уникальные значения столбца [Идентификатор просмотра], и в столбец с названием [Процент прокрутки] выводим максимальное значение столбца [Ярлык события] в заданной группе CURRENTGROUP.
Далее нам нужно эти сводные данные вывести с учетом фильтра по категории. Для этого используем функцию CALCULATETABLE, которая выведет табличное выражение GROUPBY c учетом фильтра FILTER, с помощью которой мы сможем вычленить из исходных данных только данные категории Max Scroll.
FILTER ( 'События'; 'События'[Категория событий] = "Max Scroll" )
Результатом функции CALCULATETABLE будет вот такая таблица (справа):

По ней хорошо видно, что расчеты верны, и таблица содержит максимальные значения процента прокрутки для каждого просмотра.
Итак, нам осталось посчитать средний процент прокрутки по полученной сводной таблице, для этого используем функцию AVERAGEX. Остановимся подробнее на этой функции.
Синтаксис у нее такой:
AVERAGEX ( Таблица; Выражение )
где:
- Таблица — исходная таблица или табличное выражение, в которой построчно будет вычисляться выражение из второго аргумента. В нашем случае это наша «виртуальная» таблица с данными максимальных значений прокрутки.
- Выражение — любое выражение, которое в первую очередь выполняется над каждой строкой таблицы из первого аргумента.
В нашем случае вторым аргументом является столбец «виртуальной» таблицы, взятый без изменений и над ним не производится никаких вычислений, но тем не менее мы используем именно итератор AVERAGEX, потому что работаем не со столбцом нашей модели, а с «виртуальной», специально искусственно созданной нами таблицей, о которой мы рассказывали выше.
Таким образом, функция-итератор AVERAGEX работает поэтапно. Сначала вычисляется выражение из второго аргумента для каждой строки таблицы, указанной в первом аргументе. Затем функция агрегирует эти значения и считает среднее по данным, получившимся по итогам расчета Выражения.
Аналогично работают и другие функции-итераторы, например SUMX — сначала рассчитывает построчно результат Выражения, а затем суммирует эти данные; а MAXX — также сначала выполняет действия над каждой строкой Таблицы из первого аргумента, в соответствии с Выражением из второго, а затем берет максимальное из значений всех строк.
Итак, итератор MAXX позволяет нам посчитать максимальный процент прокрутки по нашей «виртуальной» таблице.
Обратим внимание на то, что полученный результат мы еще делим на 100. Это связано с тем, что проценты в исходной таблице заданы не в процентном выражении (например, 44%), а просто как число — 44. Если в этом случае не делить на 100, то мы получили бы 4400%.

Разделив же на 100, наша меру будет возвращать значение в виде десятичной дроби: 0,44 и для отображения значения в %% останется только на вкладке Моделирование выбрать % формат представления числа:

Готово:

И напоследок рассмотрим еще одну сложную меру, которая, также как и предыдущая, содержит несколько вложенных функций. Надеемся, что на этом этапе вам уже стало немного понятно как и что считают упомянутые меры, поэтому на этот раз мы уже не будем сильно вдаваться в подробности расчетов.
Рассмотрим меру, рассчитывающую кол-во новых пользователей. Выглядит она так:
Новые пользователи := COUNTROWS ( FILTER ( CALCULATETABLE ( ADDCOLUMNS ( VALUES ( 'Сеансы'[Идентификатор пользователя] ); "Дата первого сеанса"; CALCULATE ( MIN ( 'Сеансы'[Дата] ) ) ); ALL ( 'Параметры дат' ) ); CONTAINS ( VALUES ( 'Параметры дат'[Дата] ); 'Параметры дат'[Дата]; [Дата первого сеанса] ) ) )
Рассмотрим синтаксис снаружи-внутрь. Функция COUNTROWS считает кол-во строк в таблице, возвращаемой функцией FILTER, и отфильтрованной по заданным параметрам.
Обратим внимание, что функция фильтрует строки, т.е. столбцы результирующей таблицы остаются неизменны и совпадают со столбцами фильтруемой таблицы, а строки отображаются только те, которые удовлетворяют условию фильтрации.
Как правило эта функция используется не самостоятельно, а внутри DAX выражений, и позволяет создавать промежуточные «виртуальные» таблицы, вместо обычных.
Разберем, что же в итоге получается в результате работы функции FILTER в нашем случае:
FILTER ( Таблица; Фильтр )
Таблицу, которая подвергается фильтрации, возвращает функция:
CALCULATETABLE ( ADDCOLUMNS ( VALUES ( 'Сеансы'[Идентификатор пользователя] ); "Дата первого сеанса"; CALCULATE ( MIN ( 'Сеансы'[Дата] ) ) ); ALL ( 'Параметры дат' ) )
С помощью функции ADDCOLUMNS мы к таблице, состоящей из одного столбца с уникальными идентификаторами пользователей, сформированной выражением VALUES ( ‘Сеансы'[Идентификатор пользователя] ), добавляем столбец под названием [Дата первого сеанса], и содержит он следующие значения:
CALCULATE ( MIN ( 'Сеансы'[Дата] ) )
минимальную (первую) дату сеанса, т.е по сути появление нового пользователя.
Затем, с помощью функции CALCULATETABLE, получаем нужную нам для дальнейших расчетов таблицу, при этом мы снимаем фильтр с помощью функции ALL ( ‘Параметры дат’ ), тем самым охватывая уже весь период времени. Это значит, что в этой функции на таблицу ‘Параметры дат’ не наложены фильтры.
А условие фильтрации полученной выше таблицы, в свою очередь выглядит так:
CONTAINS ( VALUES ( 'Параметры дат'[Дата] ); 'Параметры дат'[Дата]; [Дата первого сеанса] )
Это означает, что таблицу из первого аргумента функции FILTER мы фильтруем таким образом, чтоб выполнялось условие: набор уникальных дат, который возвращает функция VALUES ( ‘Параметры дат'[Дата] ) должен содержать даты, соответствующие дате первого сеанса, созданной выше. Таким образом, отбирая в справочнике дат только даты первого сеанса, мы отберем именно новых пользователей.
Надеемся, что с мерами теперь стало немного понятнее, рассмотрим теперь вычисляемые столбцы, которые также можно создавать и использовать в Power BI. Напомним, что в отличие от мер, значения таких столбцов рассчитываются для каждой строки таблицы отдельно.
В отчете они активно используются для ABC анализа. Так, прежде всего рассчитывается показатель [Накопительный просмотр страниц].
Накопительный просмотр страниц = CALCULATE ( SUM ( 'Просмотры страниц'[Количество просмотров] ); ALL ( 'Страницы' ); 'Страницы'[Просмотров страницы] >= EARLIER ( 'Страницы'[Просмотров страницы] ) )
Далее производится подсчет суммы количества просмотров для всех страниц с помощью накопительного итога. То есть, в этой сумме для каждой страницы учтены только те просмотры, которые были посчитаны ранее.
Поскольку в ABC анализе производится сравнение накопительного процента с граничными значениями, необходимо предыдущий показатель перевести в процент. Для это создаем дополнительный столбец, где каждое значение столбца [Накопительный просмотр страниц] делим на общую сумму просмотра страниц.
Накопительный процент = 'Страницы'[Накопительный просмотр страниц] / SUM ( 'Страницы'[Просмотров страницы] )
В конце нам требуется отнести все страницы в одну из трех групп:
ABC Класс = SWITCH ( TRUE (); 'Страницы'[Накопительный процент] <= 0,7; "A"; 'Страницы'[Накопительный процент] <= 0,9; "B"; "C" )
Выражение основано на одной функции SWITCH, которая по сути является «переключателем» и предназначена для возвращения определенного значения в зависимости условия которое выполнилось.
SWITCH ( Выражение; Значение; Результат )
Первым параметром может выступать любое выражение на DAX, результатом вычисления которого является единственное значение, в нашем случае это TRUE(), которое возвращает логическое значение истина. В качестве же значений, которые используются для выбора возвращаемого результата у нас используются сравнения, результаты выполнения которых сопоставляются с TRUE(). Так, мы каждую строку столбца ‘Страницы'[Накопительный процент] проверяем на удовлетворение одному из двух условий <=0,7 и <=0,9, и если накопительный % меньше или равен 0,7 (70%), то для заданной строки будет проставлена категория А, если меньше или равен 0,9 (90%) — то категория В, а если данные в строке не удовлетворяют ни одному из условий, то категория будет С.
На этом закончим наше первое (и при этом довольно масштабное) знакомство с DAX и оставим материал для других статей на эту тему.
К чему же мы пришли? А пришли мы к выводу о том, что DAX является неотъемлемой частью Power BI и правильное понимание мер и вычисляемых столбцов ощутимо помогает строить качественную и быструю отчетность. Мы разобрали отличия между мерами и вычисляемыми столбцами, и рассмотрели практические примеры использования популярных функций, разобрали синтаксис построения формул и ознакомились с нюансами таких мер, как итераторы.
Также, мы затронули такую интересную тему, как АВС анализ. И кто знает, может скоро мы даже посвятим ему отдельную небольшую статью 🙂
