[知识体系] 理解 USERELATIONSHIP

  [复制链接]
查看94317 | 回复111 | 2021-2-21 19:03:13 | 显示全部楼层 |阅读模式
CALCULATE 的另一项功能是在表达式求值期间激活关系。事实上,正如你已经知道的,数据模型可能同时包含活动关系和非活动关系。你很可能会遇到非活动关系的情况,因为当两个表之间有许多关系时,只允许存在一个活动关系。


示意:活动关系(实线)和非活动关系(虚线)

语法
  1. USERELATIONSHIP ( <ColumnName1>, <ColumnName2> )
复制代码

USERELATIONSHIP 不返回任何值;该函数只在计算期间启用指定的关系,使用时不区分两个列参数的前后顺序。


USERELATIONSHIP 中,关系的状态并不重要;也就是说,关系是否活动并不影响函数的使用。即使关系是不活动的,它也会被启用,并覆盖可能出现在模型中但没有在函数参数中提到的任何其他活动关系。


对于嵌套的 CALCULATE 表达式,并且存在不止一个 CALCULATE 调用 USERELATIONSHIP 函数的情况下,那么最内层的 USERELATIONSHIP 在出现冲突或歧义将覆盖外层的的同类函数。


USERELATIONSHIP 不能引用设置行级别安全性的表。

应用案例

例如,销售表的每笔订单都存储了订单日期和交货日期。通常,你希望根据订单日期进行销售分析,但对于某些特定度量值,你希望考虑交付日期。在这种情况下,你可以在销售表和 Date 表之间创建两个关系:一个基于 OrderDateKey,另一个基于 DeliveryDateKey。一次只能激活其中一个,因为你通常根据订单日期分析销售情况,所以你保持与 OrderDateKey 的关系处于活动状态,而另一个则处于不活动状态。然后,你需要创建一个基于给定日期统计交付数据的度量值,以便与订单数据进行比较。这个新度量值(交付数量)应该使用非活动关系来计算销售额,同时断开与订单日期的关系。


要解决这个问题,可以借助 CALCULATE 和 USERELATIONSHIP,代码如下所示
  1. [Delivered Amount] :=
  2. CALCULATE (
  3.     [Sales Amount],
  4.     USERELATIONSHIP ( Sales[DeliveryDateKey], Date[DateKey] )
  5. )
复制代码

DeliveryDateKey 和 DateKey 之间的关系将在[Delivered Amount]计算时被激活,同时与 OrderDateKey 的关系将被停用。下图你可以看到一个数据透视表,它显示了基于 OrderDateKey 计算的销售额和基于 DeliveryDateKey 计算的销售额之间的不同。


7115211936391.jpeg

此图说明了订单销售额和交付销售额的显著不同


当使用 USERELATIONSHIP 激活关系时,你需要注意一个非常重要的现象:关系的定义发生在调用表的时候,而不是在调用 RELATED 或其他关系函数的时候。


例如,如果你想计算 2007 年交付的产品数量,这个公式将不起作用:
  1. [Delivered Amount in 2007_wrong] :=
  2. CALCULATE (
  3.     [Sales Amount],
  4.     FILTER (
  5.         Sales,
  6.         CALCULATE (
  7.             RELATED ( Date[CalendarYear] ),
  8.             USERELATIONSHIP ( Sales[DeliveryDateKey], Date[DateKey] )
  9.         ) = 2007
  10.     )
  11. )
复制代码

原因在于 FILTER 迭代销售表(发生对销售表的调用),然后计值条件表达式。在计值期间,它更改了活动关系,然后调用 RELATED。但是,销售表和日期表之间的关系是在调用 FILTER 时定义的,而不是在使用 RELATED 的时候。另外,CALCULATE 内部也不存在可供调用的行上下文


如果你想执行一个类似上面的计算,需要用以下方式重写这个度量值:
  1. [Delivered Amount in 2007_still wrong] :=
  2. CALCULATE (
  3.     [Sales Amount],
  4.     FILTER (
  5.         CALCULATETABLE (
  6.             Sales,
  7.             USERELATIONSHIP ( Sales[DeliveryDateKey], Date[DateKey] )
  8.         ),
  9.         RELATED ( Date[Calendar Year] ) = 2007
  10.     )
  11. )
复制代码

在后一个公式中,销售表是在 CALCULATETABLE 激活所需的关系之后调用的。因此,FILTER 内部对 RELATED 的调用也发生在 DeliveryDateKey 关系被激活的情况下。


这种行为使得在计算列中使用非默认关系成为一种复杂的操作,因为计算列中已经隐含了对表的调用,你无法控制它,也无法使用 CALCULATE 和 USERELATIONSHIP 更改该行为*。
实际上,在 DAX 权威指南第一版中,最后这个重写的度量值仍然是错误的,原因在于虽然 FILTER 的结果使用了修改后的关系,但是外层的 CALCULATE 的初始环境仍然使用了默认的关系,这使得最终结果返回空值。这里保留了公式,仅作为错误示范

正确写法:
  1. [Delivered Amount in 2007_right] :=
  2. CALCULATE (
  3.     [Sales Amount],
  4.     USERELATIONSHIP ( Sales[DeliveryDateKey]; 'Date'[DateKey] ),
  5.     'Date'[Calendar Year] = 2007
  6. )
复制代码
深入理解 USERELATIONSHIP

未完待续
回复

使用道具 举报

slonecn | 2021-4-23 23:55:35 | 显示全部楼层
谢谢网站确实不错,超值
回复

使用道具 举报

路人乙 | 2021-5-19 07:01:33 | 显示全部楼层
有空大家一起交流一下
回复

使用道具 举报

ewayfree | 2021-7-15 13:50:38 来自手机 | 显示全部楼层
支持支持再支持
回复

使用道具 举报

四方木 | 2021-9-3 20:32:47 | 显示全部楼层
锄禾日当午,发帖真辛苦。谁知坛中餐,帖帖皆辛苦!
回复

使用道具 举报

飞翔吧 | 2021-9-9 10:55:19 来自手机 | 显示全部楼层
锄禾日当午,发帖真辛苦。谁知坛中餐,帖帖皆辛苦!
回复

使用道具 举报

缺一 | 2021-10-2 10:00:45 | 显示全部楼层
前排支持下
回复

使用道具 举报

Turbo | 2021-10-28 09:24:58 | 显示全部楼层
我擦!我要沙发!
回复

使用道具 举报

奔奔兔 | 2021-11-20 17:09:11 | 显示全部楼层
LZ帖子不给力,勉强给回复下吧
回复

使用道具 举报

dg_gaga | 2021-12-3 08:13:48 来自手机 | 显示全部楼层
不错不错.,..我一直很喜欢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则