Страницы: 1
RSS
DAX. Логика табличного фильтра в мере, Хочу понять в точности логику табличного фильтра в мере, заданной с помощью функции CALCULATE и изменённой активной связью с помощью функции USERELATIONSHIP
 
Здравствуйте, знатоки DAX!

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

Пример меры:
Код
Multiple Sales := 
CALCULATE(
    [Sales Amount],
    FILTER(
        Sales,
        'Sales'[Quantity] > 1
    )
)

Данная мера использована в матрице, где в строки выведены бренды - скрин

Объясню, как я понимаю логику работы этой меры.
1. Таблица Sales фильтруется по Brand, далее фильтруется по количеству Quantity больше 1.
2. Отфильтрованная таблица поступает как условие фильтра для меры [Sales Amount]
И тут у меня вопрос: правильно ли я понимаю, что внешний фильтр по брендам не действует на меру [Sales Amount], так как таблица Sales уже отфильтрована по Brand, а так как таблица Sales расширенная по отношению к таблице Product, то включает связанный столбец Product[Brand] ?

Если так, тогда я не понимаю, почему другая мера:
Код
Delivered Amount := 
CALCULATE (
    [Sales Amount],
    CALCULATETABLE (
        Sales,
        USERELATIONSHIP ( Sales[Delivery Date], 'Date'[Date] )
    )
)

выдаёт пустые значения. Мера используется в матрице, где в строки выведены годы - скрин1

Ведь тут же по идее та же логика.
1. Таблица Sales связана с таблицей 'Date' по дате доставки.
2. Таблица Sales, связанная с таблицей 'Date' по дате доставки, фильтруется по году из внешнего контекста фильтра.
3. Отфильтрованная таблица Sales поступает как условие фильтра для меры [Sales Amount]
Получается, что внешний фильтр по годам не действует на меру [Sales Amount], так как таблица Sales расширенная по отношению к таблице 'Date' и включает годы (годы доставки).

В книге "Подробное руководство по DAX" пустые значения меры объяснены тем, что таблица с привязкой к дате заказа пытается отфильтровать таблицу с привязкой к дате доставки, но откуда вдруг появилась эта таблица с привязкой к дате заказа, когда в формуле задана привязка к дате доставки, я не понимаю.

Помогите разобраться, пожалуйста!

Ссылка на файл - ссылка
Изменено: Дмитрий Никитин - 26.07.2024 19:09:25
Шлюхогон42
 
Дмитрий Никитин, добрый день. Я конечно когда-то читал умные книжки, но бол-во уже позабыл, поэтому я так, своими словами попробую.
1. CALCULATE - самая мощная функция, которая позволяет менять контексты фильтров с помощью других вложенных функций. То же и про CALCULATETABLE(), только она не значение дает, а таблицу, которую дальше нужно считать.
Цитата
Дмитрий Никитин написал:
Если так, тогда я не понимаю, почему другая мера:
вот то, что Вы написали, честно говоря, бессмыслица какая-то. Если цель стоит посчитать продажи по дате доставки, то тогда достаточно написать:
Код
Delivered Amount = 
CALCULATE (
    [Sales Amount],   
        USERELATIONSHIP ( Sales[Delivery Date], 'Date'[Date] )
    )

Теперь объясняю, почему не срабатывает Ваш вариант. Внутри CALCULATETABLE() вы используете USERELATIONSHIP() и изменили связь. По сути вы сделали таблицу, где есть столбец "Quantity" и "Delivery Date" в формате даты. Далее Вы хотите посчитать сумму по данной измененной таблице внутри CALCULATE(). Тут возникает одно НО. В функцию CALCULATE() не передан модификатор USERELATIONSHIP(), она только внутри CALCULATETABLE() и соответственно CALCULATE() продолжает считать по текущей активной связи с датой "OrderDataKey". А теперь обратите внимание, что в этих двух столбцах форматы дат абсолютно разные  "OrderDataKey" и "Delivery Date". Поэтому CALCULATE() и выдает BLANK(), т.к. форматы дат абсолютно не совпадают. Если продолжить Вашу логику рассуждения, то Вам нужно было бы написать так:
Код
Delivered Amount = 
CALCULATE (
    [Sales Amount],
    CALCULATETABLE (
        Sales,
        USERELATIONSHIP ( Sales[Delivery Date], 'Date'[Date] )
    ),
    USERELATIONSHIP ( Sales[Delivery Date], 'Date'[Date] )
)
но это бессмысленно, потому что проще делать так, как я выше уже сделал. Результат одинаковый.
 
Большое спасибо за ваш ответ!

Цитата
написал:
Тут возникает одно НО. В функцию CALCULATE() не передан модификатор USERELATIONSHIP(), она только внутри CALCULATETABLE() и соответственно CALCULATE() продолжает считать по текущей активной связи с датой "OrderDataKey".
Я почти начал понимать вашу логику, но тут вспомнил изначальный вопрос. В мере:
Код
Multiple Sales := 
CALCULATE(
    [Sales Amount],
    FILTER(
        Sales,
        'Sales'[Quantity] > 1
    )
)
внешний фильтр по Brand не действует на меру [Sales Amount] - скрин ?

Таблица Sales фильтруется по внутреннему фильтру Quantity и внешнему Brand и поступает как внутренний фильтр для меры [Sales Amount]. Внешний же фильтр по Brand на меру [Sales Amount] не действует, потому что таблица Sales - расширенная таблица относительно таблицы Product, в которой присутствует столбец Product[Brand], а значит таблица Sales содержит этот столбец. Получается, что таблица Sales, уже отфильтрованная по Brand, перебивает внешний фильтр по Brand.

На конечный результат эти тонкости не влияют, цифры получились бы одинаковые и в том случае, если бы [Sales Amount] фильтровалась внешним фильтром по Brand - внешний фильтр совпал бы с внутренним и на вычисления не повлиял.

Но вот в этой мере
Код
Delivered Amount := 
CALCULATE (
    [Sales Amount],
    CALCULATETABLE (
        Sales,
        USERELATIONSHIP ( Sales[Delivery Date], 'Date'[Date] )
    )
)
этот вопрос куда важнее.

Цитата
написал:
CALCULATE() продолжает считать по текущей активной связи с датой "OrderDataKey"
Если я прав относительно меры [Multiple Sales], значит не должен считать по текущей активной связи с датой "OrderData", разве нет?

Таблица Sales, привязанная к таблице 'Date' по связи Sales[Delivery Date] с 'Date'[Date], уже отфильтрована по году - году доставки. Столбец с годом присутствует в таблице Sales, так как она расширенная относительно таблицы 'Date'. Значит таблица Sales, отфильтрованная по году доставки, поступает как внутренний фильтр для меры [Sales Amount], а внешний фильтр по годам на меру [Sales Amount] не действует, так как внутренний фильтр - расширенная таблица Sales со столбцом [Calendar Year] -  перебивает внешний.  
Шлюхогон42
 
Цитата
Дмитрий Никитин написал:
внешний фильтр по Brand не действует на меру [Sales Amount] - скрин ?
я перечитал несколько раз, но так и не понял, в чем проблема у Вас? Почему Вы считаете, что внешний фильтр не действует? Вот ваши же меры в разрезе брендов, что в их поведении вызывает смущение?
 
Цитата
написал:
я перечитал несколько раз, но так и не понял, в чем проблема у Вас? Почему Вы считаете, что внешний фильтр не действует?
Я писал, что внешний фильтр не действует на 1-ый аргумент функции CALCULATE - [Sales Amount] в мере [Multiple Sales]
Код
Multiple Sales := 
CALCULATE(
    [Sales Amount],
    FILTER(
        Sales,
        'Sales'[Quantity] > 1
    )
)
Потому что внешний фильтр по Product[Brand] фильтрует 2-й аргумент функции CALCULATE:
Код
FILTER(
        Sales,
        'Sales'[Quantity] > 1
    )
А таблица Sales - расширенная относительно таблицы Product, значит включает связанный столбец Product[Brand], поэтому внешний фильтр по  Product[Brand] на 1-ый аргумент функции CALCULATE - [Sales Amount] - не действует - скрин

И если это так, тогда я не понимаю, откуда взялся внешний фильтр по годам на 1-ый аргумент функции CALCULATE - [Sales Amount] в мере [Delivered Amount] по связи Sales[OrderDate] с 'Date'[Date] ?
Шлюхогон42
 
Дмитрий Никитин, у Вас по-моему каша в голове. Все фильтры действуют в мере и внешние (бренд, год) в матрице, и внутренние ('Sales'[Quantity] > 1).
В данном случае расчет идет по активной связи календаря (OrderDateKey - DateKey) и в матрице внешний контекст фильтров срабатывает как нужно (Product[Brand] и КалендарьГод.

Если еще не понятно, давайте от обратного: вот Вы на скрине пишите
, что product[Brand] не фильтрует первую часть выражения. Докажите, какие результаты по Вашему должны получиться? (проверьте в Excel) формулами например.
Цитата
Дмитрий Никитин написал:
И если это так, тогда я не понимаю, откуда взялся внешний фильтр по годам на 1-ый аргумент функции CALCULATE - [Sales Amount] в мере [Delivered Amount] по связи Sales[OrderDate] с 'Date'[Date] ?
как откуда? Отсюда
Код
Delivered Amount = 
CALCULATE (
    [Sales Amount],   
        USERELATIONSHIP ( Sales[Delivery Date], 'Date'[Date] )
    )

USERELATIONSHIP() на то и нужен, чтобы "забить" на установленные активные связи и рассчитать по другой не активной.
Изменено: Vladimir Ch - 31.07.2024 09:55:33
 
Цитата
написал:
у Вас по-моему каша в голове. Все фильтры действуют в мере и внешние (бренд, год) в матрице, и внутренние ('Sales'[Quantity] > 1)
Нет у меня никакой каши в голове!
Вот привожу вам выдержку из книги "Подробное руководство по DAX":
Цитата
Результатом вызова функции FILTER является ограниченный набор строк из таблицы Sales. А мы помним, что в DAX любое обращение к таблице подразумевает её расширенную версию. Поскольку таблица Sales объединена связью с таблицей Product, её расширенная версия будет также включать все столбцы из таблицы Product. И в числе прочих здесь будет и столбец Product[Brand]

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

Но так как в результирующем наборе на выходе функции FILTER также содержится информация о бренде, она будет обладать большим приоритетом... В результате мы... будем видеть итоговое значение по мере Sales Amount для всех транзакций с количеством проданных товаров, превышающих единицу, вне зависимости от выбранного бренда.

Вот на основании этого я и делаю вывод, показанный тут - скрин

Цитата
написал:
как откуда? Отсюда
И далее вы приводите другую формулу меры, по которой у меня как раз нет никаких вопросов.

Напомню, мой вопрос по формуле меры:
Код
Delivered Amount := 
CALCULATE (
    [Sales Amount],
    CALCULATETABLE (
        Sales,
        USERELATIONSHIP ( Sales[Delivery Date], 'Date'[Date] )
    )
)
Откуда  взялся внешний фильтр по годам на 1-ый аргумент функции CALCULATE - [Sales Amount] в мере [Delivered Amount] по связи Sales[OrderDate] с 'Date'[Date] ?
Шлюхогон42
 
Цитата
Дмитрий Никитин написал:
В результате мы... будем видеть итоговое значение по мере Sales Amount для всех транзакций с количеством проданных товаров, превышающих единицу, вне зависимости от выбранного бренда.
как это должно выглядеть? В вашей же модели данных все нормально! таблица sales  и мера [Multiple Sales] отрабатывают корректно. В матрице сумма разбивается по брендам? Разбивается. Так почему Вы продолжаете писать одно и тоже, что Вы прочитали и таким образом понимаете. Может все же Вы просто что-то неправильно поняли? Еще раз, Вы не привели ни одно факта, что у Вас мера [Multiple Sales] работает некорректно (не учитывает контекст по Product[Brand]), но упорно продолжаете про это писать, потому что Вы так поняли цитату. Напишите страницу, откуда цитата. А то пока....ладно, не буду писать.
Цитата
Дмитрий Никитин написал:
Откуда  взялся внешний фильтр по годам на 1-ый аргумент функции CALCULATE - [Sales Amount] в мере [Delivered Amount] по связи Sales[OrderDate] с 'Date'[Date] ?
О чем Вы пишите?  столбец Sales[OrderDate] не учувствует ни в одной из связей (активная, неактивная), ни в функции USERELATIONSHIP(). По умолчанию связь активная по sales[OrderDataKey] и Calendar[DateKey], отсюда и фильтр и агрегация по годам. В чем проблема я не понимаю. Про поведение Вашей "некорректно" написанной меры [Delivered Amount] я пытался объяснить в сообщение #2. Если не понятно, извините, по другому объяснить не могу. Пишу последний раз: приведите примеры, какой результат Вы ожидаете получить в 1-ом и 2-ом случае работы мер, тогда можно конкретно о чем то говорить. Пока я вижу, что у Вас все-таки каша в голове. А меры отрабатывают ровно так, как и написаны.
Изменено: Vladimir Ch - 01.08.2024 07:46:26
 
Цитата
написал:
мера [Multiple Sales] отрабатывают корректно. В матрице сумма разбивается по брендам? Разбивается. Так почему Вы продолжаете писать одно и тоже, что Вы прочитали и таким образом понимаете. Может все же Вы просто что-то неправильно поняли? Еще раз, Вы не привели ни одно факта, что у Вас мера [Multiple Sales] работает некорректно
Да я и не утверждаю, что мера [Multiple Sales] работает некорректно! Всё нормально с этой мерой. Я только пытаюсь понять, как в точности в этой мере происходит расчёт? Правильно ли я понимаю, что первый аргумент функции CALCULATE фильтруется ТОЛЬКО внутренним фильтром (2-й аргумент функции).

Внешний же фильтр - Product[Brand] отработал на этапе фильтрации 2-го аргумента:
Код
FILTER(
        Sales,
        'Sales'[Quantity] > 1
    )
см. выдержку из книги.

Цитата
написал:
Напишите страницу, откуда цитата. А то пока....ладно, не буду писать.
Страницы: 487, 488

Цитата
написал:
Пишу последний раз: приведите примеры, какой результат Вы ожидаете получить в 1-ом и 2-ом случае работы мер, тогда можно конкретно о чем то говорить.
Я хочу получить одинаковый результат так:
Код
Delivered Amount := 
CALCULATE (
    [Sales Amount],   
        USERELATIONSHIP ( Sales[Delivery Date], 'Date'[Date] )
    )
и так:
Код
Delivered Amount := 
CALCULATE (
    [Sales Amount],
    CALCULATETABLE (
        Sales,
        USERELATIONSHIP ( Sales[Delivery Date], 'Date'[Date] )
    )
)
а сейчас вижу во втором случае пустые значения и не понимаю, почему так происходит.

А не понимаю я исходя из той логики, которую я описывал на примере меры [Multiple Sales] - внешний фильтр по годам отработал на втором аргументе функции CALCULATE:
Код
    CALCULATETABLE (
        Sales,
        USERELATIONSHIP ( Sales[Delivery Date], 'Date'[Date] )
    )
Изменено: Дмитрий Никитин - 01.08.2024 22:16:57
Шлюхогон42
 
Цитата
Дмитрий Никитин написал:
а сейчас вижу во втором случае пустые значения и не понимаю, почему так происходит.
Потому что я уже писал с самого начала про это, вот вижимка:
Цитата
Vladimir Ch написал:
Тут возникает одно НО. В функцию CALCULATE() не передан модификатор USERELATIONSHIP(), она только внутри CALCULATETABLE() и соответственно CALCULATE() продолжает считать по текущей активной связи с датой "OrderDataKey". А теперь обратите внимание, что в этих двух столбцах форматы дат абсолютно разные  "OrderDataKey" и "Delivery Date". Поэтому CALCULATE() и выдает BLANK(), т.к. форматы дат абсолютно не совпадают.
Теперь на картинках тогда:

Чтобы Ваша мера заработала в том виде, котором Вы ее написали, добавьте третью связь с Date по столбцам Sales[OrderDate] и Date[Date] и сделайте активной по умолчанию. Теперь типы данных активной связи и неактивной (DeliveryDate) будут одинаковыми и мера заработает.
Я ушел в отпуск, это мое последнее сообщение в данной теме.
 
Цитата
написал:
Чтобы Ваша мера заработала в том виде, котором Вы ее написали, добавьте третью связь с Date по столбцам Sales[OrderDate] и Date[Date] и сделайте активной по умолчанию. Теперь типы данных активной связи и неактивной (DeliveryDate) будут одинаковыми и мера заработает.
Это я сделал после первого же вашего сообщения
Активная связь по умолчанию - скрин1
Неактивная связь - скрин2

На расчёт меры:
Код
Delivered Amount := 
CALCULATE (
    [Sales Amount],
    CALCULATETABLE (
        Sales,
        USERELATIONSHIP ( Sales[Delivery Date], 'Date'[Date] )
    )
)
это никак не повлияло - скрин3

Цитата
написал:
Я ушел в отпуск, это мое последнее сообщение в данной теме.
Хорошего отпуска!
Шлюхогон42
 
Цитата
Дмитрий Никитин написал:
Это я сделал после первого же вашего сообщения
странно, я когда тестил у себя - работало
 
Цитата
написал:
странно, я когда тестил у себя - работало
Как будет возможность, пришлите, пожалуйста, ваш файл.  
Шлюхогон42
Страницы: 1
Читают тему
Наверх