精品丨CALCULATE函数进阶版知识_编程语言

CALCULATE函数详解
丨基础内容

语法=CALCULATE(<表达式>,<筛选器>,<筛选器>...)

基本用途:根据已有外部上下文构建一个新的上下文进行求值。

CALCULATE函数属于最灵活多变的函数,那么其内部到底是怎样的运行环境呢?其优先级又是怎样评定的呢?

白茶之前写过很多期关于CALCULATE函数实际运用的例子,本期呢,白茶决定详细描述一下CALCULATE函数的内部问题。

注:本期内容,属于进阶知识,不适合刚刚学习DAX的小伙伴。


精品丨CALCULATE函数进阶版知识_可视化_02

丨五大因素

首先是对于能够影响CALCULATE函数的五大因素进行系统的划分:

A、外部的双向筛选,激活与未激活的关系,例如可视化插件点击影响,这里定义为显性筛选

B、能够访问的条件,例如行上下文和切片器,这里定义为外部筛选

R、访问的条件转化为当前上下文,比如源数据是1K行,这里根据外部筛选转化为当前15行的数据,这里定义为转化筛选

S、来自内部的屏蔽器,忽略外部的影响,例如ALL函数这一类,这里定义为屏蔽筛选(也可以称之为清除筛选)。

SS、来自内部的表函数重新构造的筛选条件,例如FILTER函数这一类,这里定义为表筛选

丨优先级

然后是对于五大因素的优先级进行一个排序:

A < B < R < S < SS

即:

显性筛选<外部筛选<转化筛选<屏蔽筛选<表筛选

白茶会通过具体的案例数据,来描述一下五大因素的优先级。

精品丨CALCULATE函数进阶版知识_优先级_03

丨案例说明

模拟数据:

精品丨CALCULATE函数进阶版知识_编程语言_04

精品丨CALCULATE函数进阶版知识_优先级_05

精品丨CALCULATE函数进阶版知识_优先级_06


A、显性筛选

可能小伙伴看文字不明白什么叫显性的筛选,这里用图片说明一下。

从模型关系图片中我们能看出“切片器”这个表和“例子”表存在一对多的关系。

精品丨CALCULATE函数进阶版知识_数据_07

类似于上图的关系,两个可视化插件同时存在,这个时候两个插件可以相互的进行影响,这种情况就是双向筛选关系。

类似于模型表中激活与未激活的关系,以及双向筛选这类的,都属于显性筛选。虽然这类筛选会影响CALCULATE函数的结果,但本质上并不是影响其内部上下文顺序,因此这类影响通常是忽略不计的。

这也是为什么A级(显性筛选)优先级最低的原因。因为其只是单纯的在新上下文中起作用。


B、外部筛选

什么才叫能够访问的条件?最直观的例子是行上下文。

当我们使用CALCULATE函数对某个表达式进行聚合的时候,数据的直接来源就是行上下文。

CALCULATE根据外部的筛选条件生成新的上下文环境,一个来源于外部,一个来源于内部,因此外部的优先级是低于内部三个筛选条件的。

但是外部上下文却是CALCULATE函数的外部基石。

说具体点:

在一块空地上建了一栋别墅;

地值50W,别墅建造以及装修花了300W;

这个时候,建造费用和装修费用是评判这个别墅价值的主要原因;

但是没有这块地,这个别墅也不存在,因为是其外在的基础、基石。


R、转化筛选

每当我们使用CALCULATE函数进行外部包裹的时候,就已经进行上下文转换了,这个时候访问条件转化为内部的筛选条件。

这一过程是不受人为控制的,当外部条件和内部条件同时作用一列时,内部的优先级是大于外部的。

举个例子:

代码1:

外部筛选 =
RANKX ( ALL ( '例子' ), SUM ( '例子'[销售] ) )

代码2:

转化筛选 =
RANKX ( ALL ( '例子' ), CALCULATE ( SUM ( '例子'[销售] ) ) )

精品丨CALCULATE函数进阶版知识_编程语言_08

表1代表的可以理解为当前上下文,原始数据中白茶特地构建了三个没有数据的日期。

表2代表的是行上下文无法转化为当前上下文,这也是为什么RANKX结果全是1的原因,因为没有取到正确的值,所以无法正确排序。

表3代表的是通过CALCULATE函数将行上下文转化为了当前上下文,即当前上下文的筛选条件对于SUM聚合生效,所以能获得每一个日期对应的数据值,因此RANKX函数生效,求出正确排名。

这个时候可以理解CALCULATE是在外部筛选,即行上下文的基础上,将其进行转化生成新的上下文,即计算上下文。

精品丨CALCULATE函数进阶版知识_编程语言_09

通过显性筛选可以发现并没有对CALCULATE函数的内部运算产生影响,只是单纯的起作用,影响结果的呈现。


S、屏蔽筛选

类似于ALL这类函数的屏蔽作用,可以抵消掉前两者的影响。

例子:

屏蔽筛选 =
CALCULATE ( SUM ( '例子'[销售] ), ALL ( '例子' ) )

精品丨CALCULATE函数进阶版知识_人工智能_10

从上图中可以看到,无论是双向筛选关系,外部筛选的行上下文和切片器,还是内部产生的计算上下文,在ALL函数面前统统是失效的。

这个时候屏蔽筛选的优先级是远远大于前三者的。


SS、表筛选

类似于FILTER或者VALUES函数这种可以生成新表的表函数,优先级大于前四者。

例子1:

表筛选1 =
CALCULATE ( SUM ( '例子'[销售] ), ALL ( '例子' ), FILTER ( '例子', '例子'[日期] <= 2017 ) )

例子2:

表筛选2 =
CALCULATE ( SUM ( '例子'[销售] ), ALL ( '例子' ), VALUES ( '例子'[日期] ) )

精品丨CALCULATE函数进阶版知识_人工智能_11

从上面的动图中可以看出,CALCULATE函数内部表函数生成的筛选条件,相当于自己的亲儿子,可以完全抵消掉显性筛选、外部筛选、转化筛序以及屏蔽筛选的效果,一切以它为基准。


从上述所有的示例中,我们可以判断得出,CALCULATE函数对于执行顺序,即优先级划分是遵照前面白茶描述那样进行的:

A(显性筛选)<B(外部筛选)<R(转化筛选)<S(屏蔽筛选)<SS(表筛选)

精品丨CALCULATE函数进阶版知识_数据_12

关于行上下文和筛选上下文有时候不是那么特别容易区分,一不留神就容易搞混。

对于学过编程的小伙伴来说还好,类似于作用域。但是对于像白茶这种没接触过互联网代码的人来说,理解起来真的很吃力。

嘿神是这样说的:

行上下文类似于地球,有固定的经纬度,可以按照经纬度索引查找地理位置;

而筛选上下文是划分范围,需要知道你想上哪个国家,才会告诉你怎么去;

才会告诉你那里位于南北纬东西经的位置,那里有个什么地方。

即:筛选上下文→迭代器→激活行上下文→索引取值→值运算。

好了,关于CALCULATE函数的所有内容到本期彻底告一段落了,希望能对看到这里的小伙伴有所帮助。

至于后面的CALCULATETABLE函数,其内部的优先级原理与前者差不多,白茶就不赘述了。


这里是白茶,一个PowerBI的初学者。

精品丨CALCULATE函数进阶版知识_人工智能_13