DAX 中的双向关系及其歧义


本文翻译自国际Power BI大师Alberto Ferrari的文章——《Bidirectional relationships and ambiguity in DAX》,文中探讨了使用双向筛选器时可能出现的歧义类型。

在表格数据模型中激活双向筛选器可能会在关系链中创建不明确的路径,导致创建出数据变得难以预测的模型。本文对使用双向关系时可能出现的歧义类型进行了深入的阐释。

关系可设置为单向(默认)和双向。单向关系中,上下文筛选器可从单侧传递到多侧,但不能反向传递。换句话说,在下图中,Customer表上的筛选器会自动传递至Sales表,然而,Sales表上的筛选器不会传递到Product表上,更不会传递到Customer表或者Date表上。

file

这种情况普遍存在于大多数报表,在实际场景中,报告通常根据Customer或Product的属性划分销售额,根据销售额筛选Customer或Product是很少见的。
因此,启用双向筛选器最普遍的原因便是同步切片器。
下图的报告中有两个切片器,一个用于Customer 中的Name,另一个用于Product中的Color,右侧矩阵提供了Sales的详细信息:

file

这份报告可正常运行并能显示Amanda的采购情况,然而,Color切片器并没有筛选Amanda购买的几种颜色。通过在报告中输入颜色词条可以很轻易地看出她购买了哪种颜色,但是切片器难以向用户提供简单的反馈。原因在于Customer表上的筛选器已经传递到了Sales表,因此,它仅筛选所选用户的销售情况,但是筛选器不会自动从Sales表流向Product表,因为这两者之间已被默认设置为单向关系。
对于这个问题,有一个简单的解决方法:将Product表和Sales表之间设置为双向关系。这样做以后,筛选器会自动从Sales表传递至Product表,切片器将仅显示所选Customer的Product信息(Color等)。运行结果如下:

file

一些Power BI用户依赖双向筛选器来同步切片器,采用单向筛选器的模型简单又实用,多数情况下更新关系时既简单又方便。但是,启用简单的双向筛选器后,数据模型将复杂得难以预测。本文余下部分将详细阐释这个现象。
首先,我们来看一下新生成的模型。 它与原始模型并没有什么不同。唯一的(可忽略不计的)差异是Sales表和Product表的关系变成由双箭头表示。

file

这种双向筛选器的出现将很快给我们造成困境,因为它在模型中引入了歧义。什么是歧义?当表之间存在多条路径时,模型较为复杂。在一个关系不明确的模型中,当筛选器在表格间传输时,引擎具有多个选项。因此,它要么找到一个首选方式传输筛选器,要么就报错。在没有错误发生的情况下,要么是模型没有歧义,要么就是引擎已经找到了传递筛选器的首选方式。
现在,在继续阅读本文之前,请查看模型并检查是哪里出现了歧义。你需要根据双向筛选器的箭头找到两个通过不同路径链接起来的表格。

找到这些路径后,你会发现可以以两种不同的方式从Date表访问Purchases表:
从Date表访问Purchases表:这两个表之间存在直接关系,即下图中标记为(1)的路径。
从Date表依次访问Sales表和Product表,再到Purchases表:一条较长的路径,但完全可行,在下图中标记为(2)。
你可以从下图中查看这两条路径:
file

我们创造出一个具有歧义的模型后,引擎并没有任何提示,原因在于引擎会通过对两条路径的分析来决定首选路径。因为两个关系中,(1)是直接关系,其即为首选路径。这个选择看起来有点儿简单粗暴。因此,当需要将筛选器从Date表传递到Purchases表时,引擎会选择最短路径。

这种操作不难理解:两条路径差别非常明显。当难以选择最佳路径时,双向关系会创建出更复杂的场景,因此,引擎要选择首选路径的算法也不是那么简单。实际上,它不仅仅只是选择最短的路径,它选择的最短路径位于最接近筛选器的首选关系,最后这句话听起来可能令人费解,因为选择最佳路径的算法极其难以分析和理解。总的来说,算法几乎总是选择常人所选择的路径,但为了成为一个通用算法,其描述通常要复杂得多,这一点不再深入展开。

尽管一条路径完全优先于另一条路径,但仍可能存在将筛选器从Date表传输到Purchases表的两条路径。在某些场景下,两条路径都可通过单一的表达式传播,从而导致令人难以理解的结果,让我们来详细分析下这种情况。
我们都知道筛选器按照最直接的关系从Date表移动到Purchases表,下面这张用颜色和数字标记了路径的图展示了完整的模型。

file

试着回答以下有关该模型的简单问题:

  • Customer表是否筛选Purchases表?
  • Date表是否筛选Sales表?
  • 如果Date表和Customer表上都有筛选器,那这些筛选器对Sales表适用吗?
  • 如果Sales表可被Date表和Customer表筛选,这是否意味着Date表可通过Sales表筛选Purchases表?

前两个问题都很简单。Customer表可通过路径2筛选Purchases表,Date表可通过路径3筛选Sales表。
第三个问题则带有一点挑战性,Sales表可被Date表和Customer表筛选,Date表通过黄色路径(即路径3)筛选,Customer表通过蓝色路径(即路径2)筛选,然后Sales表通过蓝色路径(即路径2)到达Purchases表。但与此同时,Date表可通过橙色路径(即路径1)到达Purchases表,我们已知路径1是首选路径。因此,当Customer表上也有筛选器时,Date表将通过哪条路径到达Purchases表呢?现在场景开始变得复杂。毕竟,我们都知道这是一个有歧义的模型。所以,最后一个问题可推理出这样的结论:存在的筛选器越多,产生的歧义就越难解决。
双向关系模型的算法极其复杂,它会通过复杂的关系找到路径,即使该路径不是最直观的。关于这个特殊模型的正确答案如下所示:

如果Date表和Customer表都被筛选了,则两个筛选器都可用于筛选Sales表,然后Sales表筛选Product表,转而筛选Purchases表,而Date表和Sales表之间的黄色路径3则用于筛选Sales表,但是Date表也会通过最直接的关系筛选Purchases表。因此,在筛选Customer表时这两条路径都可使用。

而问题在于,根据激活的关系,消歧算法会找到不同的路径。消岐算法经过精心设计,它能够在诸多不同的场景下找到最佳路径,只是要理解它实在很复杂。为了证明这一点,本人编写了三个不同的度量值。第一个度量值仅仅只有purchase amount,接下来两个度量值本人会禁用其中一个关系:Date表和Purchases表间的关系,或是Date表和Sales表之间的关系:
第一个度量值只是purchase Quantity,接下来的两个度量值禁用其中的一个关系:Date表和Purchases表间的关系,或是Date表和Sales表之间的关系:

file

结果如下:
file

没有必要对每个单独的数字进行分析,注意到这些矩阵产生三种不同的结果就足够了。当通过CROSSFILTER禁用其中一个关系时,Date表会使用路径2或路径3筛选Purchases表。当两个关系都是活跃状态时,Data表会通过三条路径的组合筛选Purchases表,如上文所示。
我们通常将这类模型称呼为“关系迷宫”。有趣之处不在于分析数字,而是在这个迷宫中必须用DAX才能找到通往出口的路径。
本文并没有展示关于DAX的强大功能或是一些有趣的算法,本文旨在证明双向筛选器的风险性。文中展示了一个仅仅包含五个表格的简单数据模型,双向筛选器的存在已使其计算变得难以理解,更何况在实际的计算模型中,拥有数十个表的模型非常常见,情况会更加复杂。

这就是我们建议读者在数据模型中避免启用双向筛选器的原因,这并不代表双向筛选器不好,或是毫无作用。在某些情况,双向筛选器的功能确实发挥了作用。但是,我们仍需要谨慎使用双向筛选器,以确保模型不会由于双向关系而产生歧义。为了同步切片器而启用双向筛选器绝对不是最佳选项。

当然,同步切片器并不是在任何方面都不好操作,它们仍有无可替代的作用。如果同步切片器能在Power BI中通过特定查询实现客户端工具的传输,那么用户将不再为此使用双向关系。
下次如果想启用双向筛选器时,可以回顾回顾本文并试着动手操作,再确定是否真的需要设置双向筛选器。


以上内容因个人理解差异仍存在较不贴切的翻译,
想要阅读原文,
请查阅 ☛ 《Bidirectional relationships and ambiguity in DAX》
https://www.sqlbi.com/articles/bidirectional-relationships-and-ambiguity-in-dax/

如果您想深入学习微软Power BI,欢迎登录网易云课堂试听学习我们的“从Excel到Power BI数据分析可视化”系列课程。或者关注我们的公众号(PowerPivot工坊)后猛戳”在线学习”。


长按下方二维码关注“Power Pivot工坊”获取更多微软Power BI、PowerPivot相关文章、资讯,欢迎小伙伴儿们转发分享~

Power Pivot工坊