Почему не работает related dax

Содержание
  1. RELATED
  2. Синтаксис
  3. Параметры
  4. Возвращаемое значение
  5. Примечания
  6. Пример
  7. BI — это просто
  8. Простой авторский взгляд на сквозную BI аналитику (разбираем на практике Power BI, Excel, Power Pivot, DAX. и многое другое)
  9. Функции связанных значений в DAX: RELATED и RELATEDTABLE в Power BI и Power Pivot
  10. DAX функция RELATED в Power BI и Power Pivot
  11. DAX функция RELATEDTABLE в Power BI и Power Pivot
  12. Что еще посмотреть / почитать?
  13. Добавить комментарий
  14. Подписывайтесь на наши социальные сети
  15. Присоединяйтесь к нашим социальным сетям
  16. Наша группа в VK
  17. Мы в Инстаграме
  18. Наш YouTube канал
  19. Последние видео на нашем YouTube канале:
  20. Справочник DAX функций для Power BI и Power Pivot
  21. на русском языке с подробными примерами формул на практике
  22. Справочник DAX функций для Power BI и Power Pivot
  23. на русском языке с подробными примерами формул на практике
  24. Еще раз о двунаправленных связях, неоднозначности модели и USERELATIONSHIP
  25. Проблема двунаправленных связей
  26. Два активных пути между таблицами
  27. USERELATIONSHIP и выбор единственной связи между таблицами

Возвращает связанное значение из другой таблицы.

Синтаксис

Параметры

Термин Определение
гистограмма Столбец, содержащий значения, которые необходимо получить.

Возвращаемое значение

Одиночное значение, связанное с текущей строкой.

Примечания

Функция требует RELATED наличия связи между текущей таблицей и таблицей со связанными данными. Необходимо указать столбец, содержащий нужные данные, после чего функция будет использовать существующую связь «многие к одному» для получения значений из указанного столбца в связанной таблице. Если связь не существует, ее необходимо создать.

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

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

Функцию RELATED невозможно использовать для выборки столбца в ограниченной связи.

Пример

В следующем примере для создания отчета о продажах, в котором исключены данные о продажах в США, создается мера «Продажи через Интернет за пределами США». Чтобы создать меру, необходимо отфильтровать таблицу InternetSales_USD, чтобы исключить все продажи, совершенные в США, в таблице SalesTerritory. США как страна упоминаются в таблице SalesTerritory 5 раз, по одному разу для каждого из следующих регионов: Северо-Запад, Северо-Восток, Центр, Юго-Запад и Юго-Восток.

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

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

В этом случае лучше всего использовать существующую связь между InternetSales_USD и SalesTerritory, а также явно указать, что страна должна отличаться от США. Для этого создайте выражение фильтра, аналогичное следующему:

Это выражение использует функцию RELATED для поиска значения страны в таблице SalesTerritory, начиная со значения ключевого столбца SalesTerritoryKey в таблице InternetSales_USD. Результат поиска используется функцией фильтра, чтобы определить, отфильтрована ли строка InternetSales_USD.

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

В следующей таблице показаны только итоги для каждого региона, чтобы доказать, что выражение фильтра в мере («Продажи через Интернет за пределами США») работает должным образом.

Row Labels Internet Sales Non USA Internet Sales
Австралия 4 999 021,84 долл. США 4 999 021,84 долл. США
Канада 1 343 109,10 долл. США 1 343 109,10 долл. США
Франция 2 490 944,57 долл. США 2 490 944,57 долл. США
Германия 2 775 195,60 долл. США 2 775 195,60 долл. США
Соединенное Королевство 5 057 076,55 долл. США 5 057 076,55 долл. США
США 9 389 479,79 долл. США
Grand Total 26 054 827,45 долл. США 16 665 347,67 долл. США

В следующей таблице показаны результаты, которые можно получить при использовании этой меры в визуальном элементе таблицы отчета:

Источник

BI — это просто

Простой авторский взгляд на сквозную BI аналитику (разбираем на практике Power BI, Excel, Power Pivot, DAX. и многое другое)

Содержание статьи: (кликните, чтобы перейти к соответствующей части статьи):

Приветствую Вас, дорогие друзья, с Вами Будуев Антон. В этой статье мы поговорим про функции RELATED и RELATEDTABLE в Power BI и Power Pivot.

Именно эти функции позволяют, находясь в одной таблице, дотянуться до значений в другой таблице через внутренние связи DAX, настроенные во вкладке «Связи» в Power BI или Excel (Power Pivot).

Для Вашего удобства, рекомендую скачать «Справочник DAX функций для Power BI и Power Pivot» в PDF формате.

Если же в Ваших формулах имеются какие-то ошибки, проблемы, а результаты работы формул постоянно не те, что Вы ожидаете и Вам необходима помощь, то записывайтесь в бесплатный экспресс-курс «Быстрый старт в языке функций и формул DAX для Power BI и Power Pivot».

А также, подписывайтесь на наши социальные сети. Потому что именно в них, Вам будут доступны оперативно и каждый день наши актуальные фишки, секреты, наработки, примеры, кейсы, полезные советы, видео и статьи по темам сквозной BI аналитики (Power BI, DAX, Power Pivot, Excel…): Вконтакте, Инстаграм, Фейсбук, YouTube.

RELATED () — находясь в одной таблице, позволяет в рамках контекста строки получить связанное значение из второй таблицы по связи «Многие к одному».

Синтаксис: RELATED ([Столбец])

Рассмотрим пример DAX формулы с участием RELATED.

В Power BI Desktop имеются 2 исходные таблицы «Менеджеры Продажи» и «Менеджеры Отделы»:

Между ними настроена связь по полю «Менеджер» по типу «Многие к одному», то есть, много менеджеров может находится в одном отделе:

Попробуем в таблицу «Менеджеры Продажи» через связь добавить третий столбец [Отделы]:

Для этого создадим в Power BI Desktop во вкладке «Моделирование» вычисляемый столбец и постараемся в его формуле прописать столбец [Отделы] из связанной таблицы «Менеджеры Отделы»:

И по данной формуле у нас всплывает ошибка:

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

Давайте перепишем формулу вычисляемого столбца с использованием RELATED:

И вот теперь, все прошло удачно. Функция RELATED позволила нам, находясь в одной таблице, дотянуться до значения другой таблицы по связи «Многие к одному» и создать соответствующий новый столбец:

Теперь, давайте рассмотрим противоположную ситуацию. Сейчас мы будем находиться в другой таблице «Менеджеры Отделы» и в ней нам нужно будет создать новый столбец с подсчетом количества продаж каждым менеджером.

То есть, нам нужно подсоединиться через связь к таблице «Менеджеры Продажи» и там посчитать количество продаж каждого менеджера. Это количество мы можем посчитать при помощи DAX функции COUNTWROS, которая считает количество строк. Ну а подсоединяться к другой таблице через связь мы будем с помощью RELATED.

Пропишем данную формулу:

И у нас опять получилась ошибка:

На самом деле ошибка закономерна, так как функция RELATED работает по связи «Многие к одному», что у нас было соблюдено в первом примере и что мы нарушили сейчас. Так как в данном примере у нас уже связь другая, а именно «Один ко многим» (один отдел может в себе содержать много менеджеров) и с этой связью RELATED уже не работает.

Тут нам на помощь может прийти вторая функция работы по связям в DAX: RELATEDTABLE.

DAX функция RELATEDTABLE в Power BI и Power Pivot

RELATEDTABLE () — находясь в одной таблице, возвращает связанную таблицу значений из второй таблицы по связи «Один ко многим», где одна строка соответствуем многим строкам.

Синтаксис: RELATEDTABLE (‘Таблица’)

Функция RELATEDTABLE, в отличие от RELATED, уже не возвращает какое-то одно скалярное значение, она возвращает именно связанную таблицу значений, с которыми мы можем что-то сделать, например посчитать количество строк:

Давайте доработаем формулу предыдущего примера и исправим там ошибку, а именно, заменим функцию RELATED на RELATEDTABLE:

Теперь у нас все хорошо, пример формулы с RELATEDTABLE отработал отлично и посчитал нам количество продаж по каждому менеджеру:

На этом, с разбором функций связи языка DAX в Power BI и Power Pivot — RELATED и RELATEDTABLE, все.

Пожалуйста, оцените статью:

  1. 5
  2. 4
  3. 3
  4. 2
  5. 1

(39 голосов, в среднем: 5 из 5 баллов)

Успехов Вам, друзья!
С уважением, Будуев Антон.
Проект «BI — это просто»

Если у Вас появились какие-то вопросы по материалу данной статьи, задавайте их в комментариях ниже. Я Вам обязательно отвечу. Да и вообще, просто оставляйте там Вашу обратную связь, я буду очень рад.

Также, делитесь данной статьей со своими знакомыми в социальных сетях, возможно, этот материал кому-то будет очень полезен.

Понравился материал статьи?
Добавьте эту статью в закладки Вашего браузера, чтобы вернуться к ней еще раз. Для этого, прямо сейчас нажмите на клавиатуре комбинацию клавиш Ctrl+D

Что еще посмотреть / почитать?

Добавить комментарий

Подписывайтесь на наши социальные сети

Именно в них оперативно и каждый день Вам будут доступны наши актуальные фишки, секреты, наработки, примеры, кейсы, полезные советы, видео и статьи ​​по темам сквозной BI аналитики (Power BI, DAX, Power Pivot, Excel. )

Присоединяйтесь к нашим социальным сетям

Наша группа в VK

Мы в Инстаграме

Наш YouTube канал

Последние видео на нашем YouTube канале:

  • Связаться с нами: support@biprosto.ru Copyright © Проект «BI — это просто» , 2017 — 2021 ИП Будуев Антон Сергеевич. ОГРНИП 315745600033176

    Оставляя персональные данные (email, имя, логин) в формах на страницах данного сайта «BI — это просто», Вы автоматически подтверждаете свое согласие на обработку своих персональных данных

    Данный сайт «BI — это просто» при своей работе использует файлы cookie. Продолжая использовать сайт, Вы даете свое согласие на работу с этими файлами.

    Справочник DAX функций для Power BI и Power Pivot

    на русском языке с подробными примерами формул на практике

    • ищете подробное описание DAX функций для Power BI или Power Pivot на русском языке
    • нуждаетесь в примерах формул и их демонстрации на практике
    • устали разбираться с функциями самостоятельно
    • тратите огромное количество времени на создание формул методом «тыка»

    то, справочник DAX функций для Power BI и Power Pivot — это то, что Вам нужно!

    + БОНУС (видеокурс по DAX)

    Справочник DAX функций для Power BI и Power Pivot

    на русском языке с подробными примерами формул на практике

    + БОНУС: [экспресс-видеокурс] Быстрый старт в языке формул DAX для Power BI и Power Pivot

    Источник

    Еще раз о двунаправленных связях, неоднозначности модели и USERELATIONSHIP

    Двунаправленные связи в модели данных Power BI и Analysis Services позволяют эффективно решать некоторые проблемы анализа, но могут приводить к неоднозначности – ситуации, когда между таблицами существует более одного пути фильтрации. В таком случае движок DAX пытается при помощи сложного алгоритма выбрать наиболее подходящий путь, и результаты могут оказаться весьма неожиданными для разработчика.

    Знание некоторых особенностей работы алгоритма позволяет получать предсказуемые результаты при помощи функций управления связями USERELATIONSHIP и CROSSFILTER.

    В этой статье рассмотрю сразу два аспекта работы алгоритма, описание которых не встречалось мне ранее:

    1. Одно из правил выбора пути фильтрации при наличии двунаправленных связей
    2. Влияние этого правила на работу функции USERELATIONSHIP

    Проблема двунаправленных связей

    В первые несколько лет после запуска Power BI двунаправленные связи создавались в модели данных по умолчанию. Наверное, кто-то в Microsoft решил, что такая фишка будет очень удобна начинающим пользователям, создающим простые модели-звездочки с минимумом таблиц и связей между ними. Но, в конце концов, это стало приводить к нарастающему валу вопросов о «странных» результатах вычислений, и от двунаправленных связей «по умолчанию» было решено отказаться, ко всеобщему благу.

    Лучше всего сложности, связанные с двунаправленными связями, описаны в статьях Альберто Феррари и Марко Руссо на сайте sqlbi.com, а также в их книге «Подробное руководство по DAX». Например, вот такая статья «Bidirectional relationships and ambiguity in DAX» и сопутствующее ей видео прекрасно показывают суть проблемы (рекомендую ее прочесть, хотя бы при помощи онлайн-переводчика, перед тем, как двигаться дальше).

    Попробую вкратце сформулировать эту проблему так:

    1. Когда связи между таблицами однонаправленные «Один-ко-Многим» (фильтрация всегда движется от стороны связи «Один» к стороне связи «Много»), то такие модели данных обычно не вызывают проблем.
    2. Ситуацию осложняют двунаправленные связи: вполне возможна ситуация, когда фильтрация от одной таблицы к другой может пройти разными путями (неоднозначность связей).
    3. За выбор пути фильтрации в случае неоднозначности отвечает движок DAX, который руководствуется сложной системой правил для определения приоритетного пути.
    4. В некоторых случаях мы можем помочь движку определить необходимый путь фильтрации, используя функции USERELATIONSHIP и CROSSFILTER в мерах.
    5. Если у движка не получается однозначно определить путь, то во время создания связи (или же во время выполнения расчетов) возникает ошибка.

    В своей статье Феррари пишет, что алгоритм, который внутри движка DAX решает проблемы неоднозначности, слишком сложный, чтобы его можно было объяснить «на пальцах». Это действительно так, и мне пришлось недавно столкнуться с этим в рабочем проекте. Это «столкновение» подвигло меня на некоторые исследования, которые привели к удивительным выводам.

    Два активных пути между таблицами

    Для иллюстрации проблемы я сначала возьму один из демонстрационных файлов к главе 15 книги «Подробное руководство по DAX». В этом файле представлена супер-упрощенная модель данных, иллюстрирующая следующую бизнес-проблему:

    1. Учет транзакций ведется в разрезе счетов в таблице ‘Transactions’ .
    2. Клиент (таблица ‘Customers’ ) может управлять несколькими счетами (таблица ‘Accounts’ ), и у одного счёта может быть несколько владельцев.
    3. Для связи клиентов со счетами в таком случае используется таблица-мост ‘AccountsCustomers’ , которая содержит в себе пары значений AccountKey — CustomerKey

    Чтобы мы могли в такой модели ответить на вопрос: «Какой оборот по счетам каждого клиента?», мы должны сделать двунаправленной связь между таблицей-мостом ‘AccountsCustomers’ и таблицей ‘Accounts’ , таким образом, чтобы фильтр от таблицы ‘Customers’ мог добраться до таблицы ‘Transactions’ .

    Мы можем включить двустороннюю фильтрацию двумя способами:

    • Изменив направление кросс-фильтрации между ‘AccountsCustomers’ и ‘Accounts’ на двунаправленное в свойствах связи в модели (как на рисунке), и используя простую меру суммирования по столбцу:

    SumOfAmt =
    SUM ( Transactions[Amount] )

    • Используя в мере функцию CROSSFILTER с третьим аргументом Both :

    SumOfAmt CF =
    CALCULATE (
    SUM ( Transactions[Amount] ) ,
    CROSSFILTER ( Accounts[AccountKey], AccountsCustomers[AccountKey], BOTH )
    )

    Оба способа дают нам ответ на поставленный выше вопрос:

    Так, у клиента Mark суммарный оборот по его двум счетам составил 2800 (800 по личному счету «Mark» и по 1000 по совместно управляемым счетам «Mark-Paul» и «Mark-Robert»).

    В этой модели нет видимой неоднозначности связей – единственный путь от ‘Customers’ до ‘Transactions’ не создает альтернатив.

    Чтобы создать ситуацию неоднозначности, я немного модифицировал эту упрощенную модель, добавив еще две таблицы:

    • ‘Agreements’ – справочник договоров, заключенных с клиентами. У одного клиента может быть несколько договоров.
    • ‘Addendums’ – справочник дополнительных соглашений к договорам. У одного договора может быть несколько дополнительных соглашений.

    Также я добавил в таблицу ‘Transactions’ еще один столбец Transactions[AddendumKey] , который позволяет определить, в соответствии с каким из дополнительных соглашений была проведена транзакция. Теперь в этой таблице одна строка показывает операцию и в разрезе счёта Transactions[AccountKey] , и в разрезе допсоглашения Transactions[AddendumKey] .

    В итоге модель приобрела вот такой вид:

    Этот пример не является отражением лучших практик организации модели, я сделал его таким сознательно с единственной целью – продемонстрировать поведение связей.

    Теперь между таблицами ‘Customers’ и ‘Transactions’ есть два активных пути – через ‘Accounts’ и через ‘Addendums’ , и связи в модели очевидно неоднозначные. Попробуйте предположить, не заглядывая вперед, по какому же из путей пойдет фильтрация в данном случае?

    Если мы теперь посмотрим на результаты расчетов нашей меры [SumOfAmt] , то можем увидеть следующую картину:

    Таблица справа создана в новой модели данных и уже не отвечает на вопрос, поставленный ранее: «Какой оборот по счетам клиента?» Сейчас данные в ней отвечают уже на другой вопрос, который, скорее всего, звучит так: «Какой оборот по счетам клиента с учетом допсоглашений к договорам?»

    Очевидно, что в этом случае в действие вступила связь через таблицы ‘Agreements’ и ‘Addendums’ : несмотря на то, что некоторыми счетами управляют сразу два клиента («Mark-Robert» и «Mark-Paul»), таблица теперь показывает суммы только по допсоглашениям конкретных клиентов. Так, у клиента Mark оборот теперь показывается только по счетам Mark и Mark-Robert, так как операция на 1000 по счету Mark-Paul была проведена по договору клиента Paul. Аналогичная история произошла с оборотами клиента Robert.

    Как же понять, почему движком был выбран именно этот путь?

    Мы можем увидеть, что эти два активных пути распространения фильтра от ‘Customers’ имеют одно очень важное отличие: в «верхнем» пути (через ‘Accounts’ ) у нас присутствует двунаправленная связь «Многие-к-Одному» между ‘AccountsCustomers’ и ‘Accounts’ , в то время как в «нижнем» все связи однонаправленные. «Верхний» путь явно проиграл «нижнему» (через ‘Addendums’ ) в борьбе за приоритет.

    Анализ этой модели и дополнительные изыскания позволили мне сделать вывод о существовании Правила , который подтвердил один из создателей DAX Джеффри Вэнг (Jeffrey Wang):

    Путь, в котором фильтрация всегда распространяется только от стороны «Один», будет приоритетнее пути, в котором встречается распространение связи от стороны «Много»

    1. Важна именно кардинальность связи на той стороне, откуда распространяется фильтр. Например, двунаправленная связь «Один-ко-Многим» при распространении фильтра со стороны «Один» будут приоритетнее двунаправленной связи «Один-ко-Многим», в которой фильтр распространяется со стороны «Много».
    2. Место, где встречается распространение фильтра от стороны «Много», может быть где угодно в цепочке связей, не обязательно первым на пути следования фильтра.

    В нашей модели фильтр от таблицы ‘Customers’ , проходя по связи между ‘AccountsCustomers’ и ‘Accounts’ , как раз и сталкивается с такой ситуацией – он должен фильтровать таблицу ‘Accounts’ в направлении от «Много» к «Один». Анализатор связей в таком случае понижает «вес» такой связи, и движок выбирает тот путь, где такие ситуации не встречаются, т.е. путь через ‘Addendums’ .

    Для того, чтобы наша модель и в этом случае позволила нам получить такой же результат, как и ранее (оборот по счетам клиента без учета допсоглашений), мы должны задействовать отключение одной из связей на «нижнем» пути (например, связи между ‘Addendums’ и ‘Transactions ‘) при помощи функции CROSSFILTER и ее 3-го аргумента :

    SumSumOfAmt Old Path =
    CALCULATE (
    [SumOfAmt],
    CROSSFILTER ( Transactions[AddendumKey], Addendums[AddendumKey], NONE )
    )

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

    Давайте попробуем сделать неактивной одну из связей на «верхнем» пути (например, между таблицами ‘AccountsCustomers’ и ‘Accounts’ ), и затем активируем ее при помощи функции USERELATIONSHIP:

    SumOfAmtUR =
    CALCULATE (
    [SumOfAmt],
    USERELATIONSHIP ( AccountsCustomers[AccountKey], Accounts[AccountKey] )
    )

    Как видите, активация связи при помощи USERELATIONSHIP не привела ни к каким изменениям в нашем расчете – фильтрация по-прежнему идет по «нижнему» пути:

    В общем-то, трудно было ожидать изменения в данном случае:

    • При неактивной связи фильтр шел по нижнему пути – другого выбора у него не было.
    • USERELATIONSHIP просто активировала отключенную связь «верхнего» пути.
    • Так как никаких изменений в отношении пути между ‘Customers’ и ‘Transactions’ через ‘Addendums’ сделано не было, второй («нижний») путь по-прежнему приоритетен для движка, в соответствии с выведенным нами Правилом.

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

    • Если вы хотите задействовать определенный путь фильтрации между двумя таблицами, старайтесь избежать неоднозначности в связях модели.
    • Если требования модели данных не позволяют избавиться от неоднозначности, используйте функцию CROSSFILTER для изменения направления кросс-фильтрации связей или их отключения.

    Казалось бы – всё на этом, мы разобрались? Отнюдь.

    USERELATIONSHIP и выбор единственной связи между таблицами

    Следующий пример я сделал на основе реальной задачи анализа взаимосвязей между документами в Dynamics 365 Finance & Operations (AXAPTA). Как правило, в подобных ей ERP-системах существуют сложные системы отношений, которые не всегда (даже в рамках узконаправленного проекта) можно денормализовать до простой схемы «звезда» или «снежинка».

    Пусть в нашей модели есть две таблицы:

    • справочник ‘Entries’ , содержащий в себе ссылки на два разных типа документов: на расходный документ в одном столбце и на приходный документ в другом. Столбец расходных документов Entries[Issue] всегда заполнен уникальными значениями кодов документов, а в столбце приходных документов Entries[Receipt] могут встречаться незаполненные значения.
    • ‘Documents’ , содержащий в себе уникальный список документов всех видов и дополнительную информацию, которую нам нужно проанализировать.

    В модели также присутствуют и другие таблицы. Наша задача – построить связи таким образом, чтобы, приходя по связям из других таблиц, фильтрующих таблицу ‘Entries’, получить из таблицы ‘Documents’ значения, соответствующие либо расходному, либо приходному документу. Иными словами, фильтр должен распространяться от таблицы ‘Entries’ к таблице ‘Documents’ в двух вариантах:

    1. от Entries[Issue] к Documents[DocumentID]
    2. от Entries[Receipt] к Documents[DocumentID]

    Когда мы будем создавать первую связь в Power BI, движок проанализирует кардинальность столбцов с обеих сторон и, убедившись, что все значения в столбцах связи уникальные, автоматически создаст связь «Один-к-Одному»:

    Неизменяемая двунаправленность этой связи нас вполне устраивает – фильтр вполне может проходить от ‘Entries’ к ‘Documents’ , и наша задача будет отчасти решена.

    Вторую связь (от Entries[Receipt] к Documents[DocumentID] ) мы не можем сделать такой же «Один-к-Одному», так как наличие пустых значений в столбце Entries[Receipt] уже свидетельствует о неуникальности значений в нем. Поэтому движок автоматически предложит нам неактивную однонаправленную связь «Многие-к-Одному». Направление кросс-фильтрации от ‘Documents’ к ‘Entries’ нас не устраивает – нам надо наоборот. Это легко поправимо – в свойствах связи мы можем установить двунаправленную кросс-фильтрацию:

    Чтобы получить нужный нам результат, создадим две меры – одна для вычисления суммы по приходным документам, другая – по расходным:

    SumOfIssues =
    SUM ( Documents[Value] )

    SumOfReceipts =
    CALCULATE (
    SUM ( Documents[Value] ) ,
    USERELATIONSHIP ( Documents[DocumentID], Entries[Receipt] )
    )

    Мы ожидаем, что первая мера покажет нам суммы по расходным документам (связь по умолчанию), а вторая покажет суммы по приходным (за счет активации второй связи). Однако результат далёк от ожидаемого:

    В таблице слева мы получили то, что и должны были – для каждого расходного документа посчитана его сумма, а те документы, которые не нашлись в таблице ‘Entries’ , сгруппировались в пустое значение. Это стандартное поведение.

    А вот в правой таблице произошло что-то странное. Если мы еще раз посмотрим на исходные данные, то заметим, что документу E должно соответствовать значение 16, а для F мы должны получить 32. Но мы по-прежнему получили значения для спаренных с E и F расходных документов В и С.

    Несмотря на то, что мы активировали связь от столбца Entries[Receipt] , движок проигнорировал наш запрос и по-прежнему считает по первой связи – от Entries[Issue] . Это очень странно, неправда ли?

    Давайте вспомним, что мы (думаем что) знаем о связях в таком случае:

    1. Между двумя таблицами может быть только одна активная прямая связь (что вполне логично).
    2. Когда мы используем USERELATIONSHIP для активации отключенной связи между таблицами, другие прямые связи между этими двумя таблицами перестают действовать (тоже логично, иначе противоречило бы пункту 1).

    Эти два пункта на самом деле работают в абсолютном большинстве случаев (а в Power Pivot на настоящий момент – наверное, в 100% случаев). Но здесь что-то пошло не так…

    Чтобы не ходить вокруг да около, я просто еще раз приведу здесь то Правило, которое мы вывели ранее в этой статье:

    Путь, в котором фильтрация всегда распространяется только от стороны «Один», будет приоритетнее пути, в котором встречается распространение связи от стороны «Много»

    Но почему оно сработало здесь? Ведь у нас нет двух активных путей между таблицами, а активация второй связи при помощи USERELATIONSHIP должна была отключить активную связь «Один-к-Одному» по столбцу Entries[Issue] – ведь так всегда происходит?

    Я потратил на изучение этой проблемы много часов, анализируя модель, запросы, планы запросов, мучая коллег и знакомых, и, в конце концов, разработчиков Power BI. Делал я это не из праздного любопытства – приведенный пример был частью большой «боевой» модели данных, с которой я работал. В конце концов Джеффри Вэнг дал мне комментарий, который позволил пролить свет на происходящее.

    1. При использовании USERELATIONSHIP происходит не буквально «активация одной связи и деактивация другой», а, скорее, увеличение приоритета (веса) неактивной связи над активной на время расчета меры.
    2. Таким образом, в обычной ситуации неактивная связь временно получает более высокий приоритет, чем активная, и распространение фильтрации идет уже по новому пути.
    3. Однако, указанное выше правило в данном случае берет верх и расставляет приоритеты по-своему: так как неактивная связь использует фильтрацию от «Много» к «Один», ее приоритет ниже, чем приоритет связи от «Один» к «Много» (связь «Один-к-Одному» здесь трактуется так же).

    Сдвиг парадигмы, неправда ли?

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

    Система приоритетов связей была введена в целях корректной обработки сложных формул с многими «нанизанными» друг на друга (или вложенными) USERELATIONSHIP, и это очень интересное решение, которое, однако, привело к вот такому столкновению с алгоритмом обработки неоднозначных связей.

    Джеффри назвал это поведение «непоследовательностью», и, по зрелому размышлению, я с ним скорее соглашусь: да, не так, как в других случаях, но это то самое «исключение из правил». Очень маловероятно, что это будет изменено, так как может затронуть большое количество работающих моделей. И, опять же, жаль, что это нигде не было описано до сих пор. Но теперь у вас это знание есть 😊

    Что же делать в таком случае – как победить правило и получить требуемый результат?

    На самом деле – довольно просто, и для этого есть даже не одно решение:

    • Мы можем использовать в нашей мере в дополнение к USERELATIONSHIP функцию CROSSFILTER, отключающую связь «Один-к-Одному»:

    SumOfReceipts CF =
    CALCULATE (
    SUM ( Documents[Value] ) ,
    USERELATIONSHIP ( Documents[DocumentID], Entries[Receipt] ) ,
    CROSSFILTER ( Documents[DocumentID], Entries[Issue], NONE )
    )

    • Мы можем изменить кардинальность активной связи от Entries[Issue] к Documents[DocumentID] на двунаправленную «Многие-к-Одному». Тогда правило определения приоритета столкнется с двумя однотипными связями и ничего не будет делать, оставив право определения приоритета за USERELATIONSHIP

    В обоих случаях мы получим нужный результат — фильтрация заработает так, как нам нужно:

    Ну и, конечно, мы можем использовать любые варианты виртуальных связей на основе TREATAS, INTERSECT и так далее – с учетом всех связанных с ними нюансов.

    В заключение хочу привести еще одну цитату из статьи Альберто Феррари:

    The fun part is not in analyzing the numbers; the fun part lies in finding the path that DAX had to discover within the maze to find the exit.

    Действительно, DAX нам всегда что-то посчитает (в крайнем случае, выдаст ошибку, если мы грубо ошибемся), но мы должны понимать, что же именно он посчитал. А знание – сила!

    Вы можете скачать файл с примерами к данной статье здесь:

    Источник

    Читайте также:  Как настроить регистратор gs63h
  • Оцените статью