Комментарии 4
Пардон за длинный комментарий-добавление. О наболевшем :-)
Одно из ключевых преимуществ Power BI состоит в том, что код DAX в measures (метриках/вычислениях) автоматически "понимает" контекст из пользовательского интерфейса(фильтры-слайсеры, что в колонках /строчках сводных таблиц или на осях и категориях в графиках в визуализациях). При этом связи (relationships) между таблицами работают по умолчанию как фильтры, что тоже нужно учитывать.
Код с Evaluate - это обрамление вокруг метрик, которое используется при их отладке ну или в презентациях в целях демонстрации. При реальном использовании отчетов, Evaluate генерируется автоматически и пользователь (да и разработчик) его не видит (пока не захочет :-) )Т.е. реальный код DAX еще лаконичней чем в примерах.
Но! Мастерство разработчика DAX состоит как раз в написании кода метрик, которые будут работать в разных контекстах, т.е. в визуализациях с разным набором полей и на разных уровнях агрегации. Тогда модель получается элегантной и простой в использовании.
Например, более универсальная первая метрика могла бы выглядеть так:
Продажи товаров дешевле 1000 руб =
CALCULATE(SUM('Продажи'[Цена]), 'Продажи'[Цена]<1000)
И все. Если нужно посмотреть распределение по категориям/клиентам - добавляете в визуализацию (например, сводную таблицу) эти две категории и эту метрику (ну и, например, год-месяц в колонки) и получаете требуемый результат.
Нужно порезать по регионам - используете атрибут клиента "Регион" и все ту же метрику. И т.д. и т.п. Т.е. разработчик предвидит, что эта метрика будет использоваться в разных "разрезах", и избегает использования фиксированного набора категорий когда это возможно.
Кстати, рекомендуют сначала сделать базовую метрику
Сумма Продаж = SUM('Продажи'[Цена])
, а потом добавлять ее производные по мере надобности:
Продажи товаров дешевле 1000 руб =
CALCULATE([Сумма Продаж], 'Продажи'[Цена]<1000)
Продажи товаров дороже 2000 руб =
CALCULATE([Сумма Продаж], 'Продажи'[Цена] > 2000)
И т.п.
Подскажите, в Visiology это так же может быть реализовано? Или есть ограничения?
P.S.
- FILTER внутри CALCULATE в этом случае генерируется автоматически
- SUM лучше чем MAX отвечает на поставленный вопрос "Кто скупил дешевую колбасу?" :-)
Спасибо за подробную обратную связь.
DAX составляет суть Visiology в том смысле, что DAX пишется не только через UI, но и генерируется компонентами Visiology (фильтрами и другими виджетами), поддерживаются меры и вложенные меры, меры для всего набора данных и меры для одного дашборда и т.д.
Поэтому Visiology дает свободу в реализации сложных мер и использовании их в фильтрах, других виджетах и дашбордах.
Кстати, рекомендуют сначала сделать базовую метрику
Хорошая практика, Вы описываете дополнительные преимущества DAX с точки зрения архитектуры BI решения, схемы данных и визуализаций. В первом примере статьи цель была в сравнении решений задачи на DAX и SQL, поэтому для упрощения сравнения DAX был написан без меры, в третьем примере рассмотрен уже DAX с мерой.
Описанный Вами подход к расчету мер может быть эффективно реализован в Visiology.
FILTER внутри CALCULATE в этом случае генерируется автоматически
Поскольку в перечисленных случаях CALCULATE без FILTER является синтаксическим сахаром для CALCULATE с FILTER (более полный список эквивалентных DAX можно найти, например, здесь, или в других источниках), то использование в Visiology CALCULATE с FILTER не накладывает ограничений для этих случаев.
SUM лучше чем MAX отвечает на поставленный вопрос "Кто скупил дешевую колбасу?"
Справедливо и выглядит как дополнительный критерий, по объемам покупок :)
Спасибо, принято.
Кстати, SQL тоже может быть попроще. Давненько я не писал SQL-запросы (работаю с другими типами БД), но если помню правильно, то условия в WHERE применяются раньше чем GROUP BY. Тогда первый пример может выглядеть так:
SELECT product.category AS "Категория",
client.name AS "Имя клиента",
SUM(sales.price) AS "Продажи товаров дешевле 1000"
FROM sales
INNER JOIN product ON sales.productkey = product.dimproduct_productkey
INNER JOIN client ON sales.customerkey = client.dimcustomer_customerkey
WHERE sales.price < 1000
GROUP BY product.category, client.name;
Преимущества DAX на этом примере:
- Если модель данных спроектирована правильно и сценарий использует созданные там связи (relationships), то во многих случаях в DAX JOIN-ы не нужны. Связи в табулярных моделях - "активные", т.е. работают как одно- или двунаправленные фильтры между связанными таблицами. При желании их можно (пере)определить прямо в коде (например, через функции USERELATIONSHIP, TREATAS, NATURAL*JOIN и пр)
- То же относится и к GROUP BY - как минимум, в типовых случаях DAX-движок понимает из контекста что нужно агрегировать
- В SQL трудно разделить меру (метрику) и контекст. Все поля и фильтры должны явным образом включаться в запрос, что увеличивает трудоемкость разработки запросов в разы (особенно с учетом обработки "крайних случаев" - пустых значений, больших списков значений в фильтрах, "Выбрать всё" и пр). Я пока не видел такой интеграции с UI (Power BI, Excel и т.п.), которая бы позволяла генерировать их автоматически так же просто и элегантно, как это делает c DAX PowerBI или Excel.
UPDATE: Ошибся веткой
Спасибо за отличные аргументы в копилку DAX :)
По поводу SQL - согласен, вот такие есть недостатки SQL, что появляются идеи улучшений SQL кода, уже без выбора диалекта SQL, СУБД, её версии (версия до 22.02.2022 - такая версия часто рекомендуется к использованию, или после 22.02.2022, и т.д.) - достаточно много нюансов, которые отвлекают от решения основных задач, от бизнес-логики. Например, у меня встречалось, что версия СУБД до 22.02.2022 не применяет WHERE сразу до JOIN при наличии нескольких JOIN, т.е. выделение подзапросов с WHERE приводит к более эффективному плану выполнения SQL запроса в версии СУБД до 22.02.2022, но в последней версии СУБД это исправлено и можно не использовать подзапросы с WHERE.
ДАКСуем вместе: три колбасных примера для реальной аналитики