Image

Под капотом: как DAX работает с фильтрами

Объединение функций Time Intelligence для иллюстрации логики применения фильтров DAX и управления ими

Делиться

728354107403fcae2649fdda19bc32b8

Введение

Начнем с простой таблицы:

463260c16dbecb2c226915725a1ccf38

Каждая строка в матрице отображает общий объем онлайн-продаж за каждый месяц.
Все идет нормально.

Интерпретация заключается в том, что мы видим общий объем онлайн-продаж, отфильтрованный по месяцам.

Но это не вся правда.

Давайте посмотрим на модель данных:

fdca350c9611c4a0d29122bb3a1628da

Если вы посмотрите внимательно, то увидите, что между двумя столбцами дат выстроена связь.

Связи со столбцом «Месяц» нет.

Если мы пойдем этим путем, то приведенная выше интерпретация будет не совсем точной.

Полная интерпретация должна быть такой: каждая строка показывает общий объём онлайн-продаж, отфильтрованный по таблице дат. Строки таблицы дат сгруппированы по месяцам. Каждая строка показывает общий объём продаж за все дни каждого месяца.

Когда мы осознаем эту деталь, мы станем на шаг ближе к пониманию DAX в целом и функций временной аналитики в частности.

Давайте сделаем еще один шаг вперед.

YTD и базовый запрос

Теперь давайте добавим показатель YTD, чтобы посмотреть, что произойдет:

48c282a8a705ec19887d667d5838e404

Мера не представляет собой ничего особенного, и результаты легко понять.

Теперь давайте посмотрим, что именно делает функция DATESYTD().

В пояснении от dax.guide говорится: «Возвращает набор дат в году до последней даты, видимой в контексте фильтра».

Что именно это означает?

Чтобы разобраться в этом вопросе, давайте сначала напишем запрос DAX, чтобы получить список дат в июне 2024 года, как это сделано в визуализации выше:

DEFINE VAR YearFilter = TREATAS({ 2024 }, 'Дата'[Год]) VAR MonthFilter = TREATAS({ 6 }, 'Дата'[Месяц]) EVALUATE SUMMARIZECOLUMNS('Дата'[Дата],YearFilter,MonthFilter)

В результате получается список из 30 дней июня:

06411b2a9984052f894421cb775f7bae

Это фильтр, примененный к строке за июнь 2024 г. в матрице, показанной выше.

Какой результат получим, если применить функцию DATESYTD() к результату?

Вот запрос:

DEFINE VAR YearFilter = TREATAS({ 2024 }, 'Дата'[Год]) VAR MonthFilter = TREATAS({ 6 }, 'Дата'[Месяц]) VAR BasisDates = CALCULATETABLE( SUMMARIZECOLUMNS('Дата'[Дата],YearFilter,MonthFilter) ) VAR YTDDates = DATESYTD(TREATAS(BasisDates, 'Дата'[Дата]) ) EVALUATE YTDDates

И вот, результат:

db93dc4763dbc9205b8d5eb70fa68aec

Это список из 182 строк, содержащий все даты с начала года до последнего дня июня 2024 года.

Это определение YTD.

Если взглянуть на следующую меру:

Онлайн-продажи (YTD) = VAR YTDDates = DATESYTD('Дата'[Дата]) RETURN CALCULATE([Сумма онлайн-продаж] ,YTDDates )

Мы понимаем, что переменная YTDDates — это «всего лишь» список дат, примененный в качестве фильтра к функции CALCULATE().

Это ключ ко всем функциям интеллекта Времени.

Вернитесь на год назад — несколько примеров

Что произойдет, если к результату применить другую функцию?

Например, SAMEPERIODLASTYEAR()?

Чтобы ответить на этот вопрос, я использую следующий запрос DAX:

DEFINE VAR YearFilter = TREATAS({ 2024 }, 'Дата'[Год]) VAR MonthFilter = TREATAS({ 6 }, 'Дата'[Месяц]) VAR BasisDates = CALCULATETABLE( SUMMARIZECOLUMNS('Дата'[Дата],YearFilter,MonthFilter ) ) VAR YTDDates = DATESYTD(TREATAS(BasisDates, 'Дата'[Дата]) ) VAR YTDDatesPY = SAMEPERIODLASTYEAR(YTDDates) EVALUATE YTDDatesPY

Я намеренно отделил вызов SAMEPERIODLASTYEAR() от DATESYTD() для удобства чтения. Можно было бы вложить DATESYTD() в SAMEPERIODLASTYEAR().

На этот раз у нас 181 строка, поскольку 2024 год был високосным.
И даты сдвинуты на один год назад:

52738d424fcf977dc0c0ae6d43a39574

Итак, снова, когда мы применяем функцию Time Intelligence к мере, функция, например, DATESYTD(), возвращает список дат.
Обратите внимание: при применении фильтра все существующие фильтры в таблице дат удаляются.

Пользовательская логика

Теперь давайте применим эти знания к пользовательской логике временного интеллекта.

Для начала немного изменим фильтр по году и месяцу:

DEFINE VAR YearMonthFilter = TREATAS({ 202406 }, 'Дата'[MonthKey]) EVALUATE SUMMARIZECOLUMNS('Дата'[Date] , YearMonthFilter )

Результат этого запроса такой же, как и в начале статьи.

На этот раз я установил фильтр с числовым значением в столбце [MonthKey].

Как мне вернуться к предыдущему году?

Если подумать математически, то это просто вычитание 100:

202406 – 100 = 202306

Давайте попробуем:

81fa3ca19800258dce2bfb80eb138bfd

То же самое можно сделать и с другими числовыми форматами.

Если взять, например, такой финансовый год: 2425 (для финансового года 24/25)

Вы можете вычесть 101, чтобы получить номер предыдущего финансового года: 2425 – 101 = 2324.

Другим примером пользовательской логики анализа времени является скользящее среднее значение, где для каждого дня мы вычисляем среднее значение за последние 10 дней:

3366dd7b2ce49a8cb952fdb999fa83d3

Поскольку содержимое переменной DateRange снова представляет собой список дат, я могу применить к нему функцию SAMEPERIODLASTYEAR() и получить нужный мне результат:

DEFINE VAR YearFilter = TREATAS({ 2024 }, 'Дата'[Год]) VAR MonthFilter = TREATAS({ 6 }, 'Дата'[Месяц]) // 1. Получить первую и последнюю дату для текущего контекста фильтра VAR MaxDate = CALCULATE(MAX( 'Дата'[Дата] ) ,YearFilter ,MonthFilter ) VAR MinDate = CALCULATE( DATEADD( 'Дата'[Дата], — 10, ДЕНЬ ) ,'Дата'[Дата] = MaxDate ) // 2. Сгенерировать диапазон дат, необходимый для скользящего среднего (четыре месяца) VAR DateRange = CALCULATETABLE( DATESBETWEEN( 'Дата'[Дата] ,MinDate ,MaxDate ) ) EVALUATE ТОТ ЖЕПЕРИОДЛАСТГОД( Диапазон дат )

И вот результат:

1bde57b14c67c6d5730d8b26dae63239

Эта логика возвращает 11 строк, поскольку включает последний день месяца. В зависимости от требуемого результата нам необходимо скорректировать способ вычисления первой и последней дат в списке дат (фильтр, применяемый к показателю).

Конечно, это повторение того, что я показал выше. Однако это показывает, что тот же подход можно применять к различным сценариям.

Как только вы это поймете, ваша работа с функциями временной аналитики и другими функциями, принимающими в качестве входных данных таблицы значений, станет намного проще для понимания и освоения.

Заключение

Хотя для запросов я использовал DAX Studio, вы можете использовать те же запросы в инструменте запросов DAX в Power BI Desktop.

Я намеренно использовал эти запросы, чтобы продемонстрировать, что в DAX мы постоянно работаем с таблицами, даже если не всегда осознаем это.

Но это важная деталь, которая помогает нам в понимании DAX.

Хотя часть представленного здесь кода DAX может устареть с появлением новой функции анализа времени на основе календаря в Power BI, изложенные здесь принципы остаются актуальными. Такие функции, как DATESYTD() или SAMEPERIODLASTYEAR(), по-прежнему существуют и работают так же, как и раньше. В настоящее время в этом отношении ничего не изменится, поскольку описанные здесь концепции по-прежнему актуальны.

Ссылки

Как и в предыдущих статьях, я использую пример набора данных Contoso. Вы можете бесплатно скачать набор данных ContosoRetailDW с сайта Microsoft здесь.

Данные Contoso можно свободно использовать по лицензии MIT, как описано в этом документе. Я изменил набор данных, чтобы сместить данные на современные даты.

Источник: towardsdatascience.com

✅ Найденные теги: новости, Под
Каталог бесплатных опенсорс-решений, которые можно развернуть локально и забыть о подписках

галерея

Фото сгенерированных лиц: исследование показывает, что люди не могут отличить настоящие лица от сгенерированных
Нейросети построили капитализм за трое суток: 100 агентов Claude заперли…
Скетч: цифровой осьминог и виртуальный мир внутри компьютера с человечком.
Сцена с жестами пальцами, где один жест символизирует "VPN", а другой "KHP".
‼️Paramount купила Warner Bros. Discovery — сумма сделки составила безумные…
Скриншот репозитория GitHub "Claude Scientific Skills" AI для научных исследований.
Структура эффективного запроса Claude с элементами задачи, контекста и референса.
Эскиз и готовая веб-страница платформы для AI-дизайна в современном темном режиме.
ideipro logotyp
Image Not Found
Звёздное небо с галактиками и туманностями, космос, Вселенная, астрофотография.

Система оповещения обсерватории Рубина отправила 800 000 сигналов в первую ночь наблюдений.

Астрономы будут получать оповещения о небесных явлениях в течение нескольких минут после их обнаружения. Теренс О'Брайен, редактор раздела «Выходные». Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной…

Мар 2, 2026
Женщина с длинными тёмными волосами в синем свете, нейтральный фон.

Расследование в отношении 61-фунтовой машины, которая «пожирает» пластик и выплевывает кирпичи.

Обзор компактного пресса для мягкого пластика Clear Drop — и что будет дальше. Шон Холлистер, старший редактор Публикации этого автора будут добавляться в вашу ежедневную рассылку по электронной почте и в ленту новостей на главной странице вашего…

Мар 2, 2026
Черный углеродное волокно с текстурой плетения, отражающий свет.

Материал будущего: как работает «бессмертный» композит

Учёные из Университета штата Северная Каролина представили композит нового поколения, способный самостоятельно восстанавливаться после серьёзных повреждений.  Речь идёт о модифицированном армированном волокном полимере (FRP), который не просто сохраняет прочность при малом весе, но и способен «залечивать» внутренние…

Мар 2, 2026
Круглый экран с изображением замка и горы, рядом электронная плата.

Круглый дисплей Waveshare для креативных проектов

Круглый 7-дюймовый сенсорный дисплей от Waveshare создан для разработчиков и дизайнеров, которым нужен нестандартный экран.  Это IPS-панель с разрешением 1 080×1 080 пикселей, поддержкой 10-точечного ёмкостного сенсора, оптической склейкой и защитным закалённым стеклом, выполненная в круглом форм-факторе.…

Мар 2, 2026

Впишите свой почтовый адрес и мы будем присылать вам на почту самые свежие новости в числе самых первых