深入理解 Calculate 函数
我们知道 CALCULATE 是 DAX 中可以修改筛选上下文的函数。
[Measure] := CALCULATE( Expression,Condition1, ...ConditionN )
CALCULATE 只有第一个参数用来计算的表达式是必填项,而其他的都是筛选器参数。
我们还了解到 CALCULATE 可以进行上下文转换,它可以将现有的行上下文转化为筛选上下文。
CALCULATE 筛选器参数
CALCULATE 的筛选器参数,我们之前讲到过布尔值和表筛选,但实际上还有第三种筛选器参数 - CALCULATE 调节器。
布尔值筛选器参数
布尔值就是最简单的一种 CALCULATE 函数写法,比如 [性别] = "男" ,就是布尔值类型。
但布尔值的筛选器 DAX 会在背地里自动转化为 FILTER(ALL) 形式的表筛选器参数
表筛选器参数
将整张表当作筛选器条件,通常是使用 FILTER 公式来筛选对应的表
所以布尔值和表形式,实际上本质都是表筛选。
CALCULATE 调节器
除了以上两种表形式的筛选器外,CALCULATE 还接受一种叫做调节器的筛选参数。比如 ALL、ALLSELECTED、KEEPFILTERS、USERELATIONSHIP 等函数作为筛选器参数,它们不像前两种筛选器那样直接引入新的筛选上下文,而是改变筛选上下文的生成方式。
ALL 类函数
以我们之前接触过的 ALL 函数为例,ALL 函数可以移除原有的筛选上下文。(不管表内表外筛选都不影响)
当我们使用布尔值筛选的简易写法时,背后就会用到 ALL 函数来移除原有筛选上下文。
![](https://pic3.zhimg.com/80/v2-44628dcb83deed3ac7f884fa49d0baee_1440w.webp)
这时候如果我们想保留原有的筛选上下文,就需要把 ALL 删掉。
![](https://pic1.zhimg.com/80/v2-64d540162ca8f74c8c964f982233788c_1440w.webp)
和 ALL 能起到类似作用的函数还有 ALLEXCEPT, ALLNOBLANKROW, ALLSELECTED,ALLCROSSFILTERED 。只不过每一个还会有一些细微的差别。
REMOVEFILTERS
由于 ALL 函数又能作为表筛选,又能作为筛选调节器。所以在使用时,容易让人产生歧义。
这时如果我们只是想要清除原有的筛选器,则可以使用 REMOVEFILTERS 函数。
该函数的唯一作用就是作为 CALCULATE 调节器,将原有筛选上下文移除。
比如下图中我们想要计算销售额占比,这时候只在 CALCULATE 中写一个参数得到的结果就会不准确,而加上第二个筛选调节器 REMOVEFILTERS 后将原有筛选上下文清空后,就会成功显示正确的数据。
![](https://pic1.zhimg.com/80/v2-db0edceaf8d33ac5df482edcb89229dc_1440w.webp)
KEEPFILTERS
KEEPFILTERS 作为筛选调节器,不会清除,不会覆盖原有的筛选器,而是会保留现有的筛选器,并将新的筛选器追加到原有筛选上下文中。
以之前创建的【一类产品销售总金额】为例,我们当时直接用简易的布尔值写法去筛选产品分类 =一类时,数据无法正确显示,都是重复值。
当时讲过,这个原因是简易的布尔值写法,背后用到的筛选是表筛选 FILTER(ALL) , 而我们刚才也提到过 ALL 作为筛选调节器时会清除原有的筛选上下文。这时候会导致参与计算的数据只有一类产品,则所有数据的结果显示的都是一类产品的销售总金额。
当时的解决方法是改用表筛选,然后清除 ALL 。从而让筛选上下文中保留产品分类 = 二类。这时则会在 Power BI 数据中对应 二类的值显示为正确的空。
![](https://pic3.zhimg.com/80/v2-3fb9d73cc72d7b33cea0f2c4e426793a_1440w.webp)
除了这种方法外,我们也可以用 KEEPFILTERS 实现同样的效果。
![](https://pic4.zhimg.com/80/v2-97e656e04c062a40aaf0243d6fc3602b_1440w.webp)
这是因为当前的计算上下文同时有 Power BI 可视化效果中数据标签【产品分类】添加的筛选上下文,也有筛选调节器 KEEPFILTERS中新增的筛选条件【 产品分类 = 一类】, 因此这时也能正确显示数据。
USERELEATIONSHIP
CALCULATE 调节器的另一项作用就是在表达式求值期间激活关系。
之前我们提到过建模中,表和表之间的关系。如果两个表之间是虚线代表是非活动关系,实线则代表活动关系。
实线关系和虚线关系计算时只能激活一个,实线表示当前激活的关系。而如果我们想在 DAX中切换关系的激活,则需要使用 USERELEATIONSHIP 函数。这个函数不会返回任何值,唯一的作用就是在当前表达式计算时,启用指定关系。
![](https://pic1.zhimg.com/80/v2-dce666e35911d13fd17c52768d7196a4_1440w.webp)
以我们的订单明细表和日历表为例。订单明细表中的下单日期和交货日期都可以和日历表中的日期关联。
但同时只能有一个关系生效,因此另一个关系就是虚线表示。
假设现在默认是下单日期和日历表是实线活动关系,但我们想在某个度量值计算时使用到虚线关系也就是交货日期和日历表的关系,这个时候就需要在 CALCULATE 中使用USERELATIONSHIP
那我们现在的需求是分别看下不同月份的交货数量。
先用一个度量值,通过 DISTINCTCOUNT 得到排除重复值的订单数量。
![](https://pic3.zhimg.com/80/v2-4cd303d4f77323882ffd60b27a8251f6_1440w.webp)
再计算一个交货订单数量。
这时候我们在 CALCULATE 中用 USERELATIONSHIP 将日历表的日期列和订单明细表的交货日期激活关系。
那么就能得到每个月正确的交货订单数量。
![](https://pic4.zhimg.com/80/v2-6af38e31ca83d2dc543a2313f7ba1a0f_1440w.webp)
但如果我们没写后面那段 USERELATIONSHIP , 则结果将只会显示10月的订单数量。
原因是默认的活动关系是下单日期和日历之间的关系。我们当前数据的下单时间都是10月,因此Power BI 则会安装这个关系进行筛选,从而只显示 10 月, 并且在计算的时候也是基于 10 月的订单数量进行的计算。
![](https://pic3.zhimg.com/80/v2-45d1d709f2d6262862cb06803973489e_1440w.webp)
总结