CALCULATE函数详解
丨基础内容
语法=CALCULATE(<表达式>,<筛选器>,<筛选器>...)
基本用途:根据已有外部上下文构建一个新的上下文进行求值。
CALCULATE函数属于最灵活多变的函数,那么其内部到底是怎样的运行环境呢?其优先级又是怎样评定的呢?
白茶之前写过很多期关于CALCULATE函数实际运用的例子,本期呢,白茶决定详细描述一下CALCULATE函数的内部问题。
注:本期内容,属于进阶知识,不适合刚刚学习DAX的小伙伴。
丨五大因素
首先是对于能够影响CALCULATE函数的五大因素进行系统的划分:
A、外部的双向筛选,激活与未激活的关系,例如可视化插件点击影响,这里定义为显性筛选。
B、能够访问的条件,例如行上下文和切片器,这里定义为外部筛选。
R、访问的条件转化为当前上下文,比如源数据是1K行,这里根据外部筛选转化为当前15行的数据,这里定义为转化筛选。
S、来自内部的屏蔽器,忽略外部的影响,例如ALL函数这一类,这里定义为屏蔽筛选(也可以称之为清除筛选)。
SS、来自内部的表函数重新构造的筛选条件,例如FILTER函数这一类,这里定义为表筛选。
丨优先级
然后是对于五大因素的优先级进行一个排序:
A < B < R < S < SS
即:
显性筛选<外部筛选<转化筛选<屏蔽筛选<表筛选
白茶会通过具体的案例数据,来描述一下五大因素的优先级。
丨案例说明
模拟数据:
A、显性筛选
可能小伙伴看文字不明白什么叫显性的筛选,这里用图片说明一下。
从模型关系图片中我们能看出“切片器”这个表和“例子”表存在一对多的关系。
类似于上图的关系,两个可视化插件同时存在,这个时候两个插件可以相互的进行影响,这种情况就是双向筛选关系。
类似于模型表中激活与未激活的关系,以及双向筛选这类的,都属于显性筛选。虽然这类筛选会影响CALCULATE函数的结果,但本质上并不是影响其内部上下文顺序,因此这类影响通常是忽略不计的。
这也是为什么A级(显性筛选)优先级最低的原因。因为其只是单纯的在新上下文中起作用。
B、外部筛选
什么才叫能够访问的条件?最直观的例子是行上下文。
当我们使用CALCULATE函数对某个表达式进行聚合的时候,数据的直接来源就是行上下文。
CALCULATE根据外部的筛选条件生成新的上下文环境,一个来源于外部,一个来源于内部,因此外部的优先级是低于内部三个筛选条件的。
但是外部上下文却是CALCULATE函数的外部基石。
说具体点:
在一块空地上建了一栋别墅;
地值50W,别墅建造以及装修花了300W;
这个时候,建造费用和装修费用是评判这个别墅价值的主要原因;
但是没有这块地,这个别墅也不存在,因为是其外在的基础、基石。
R、转化筛选
每当我们使用CALCULATE函数进行外部包裹的时候,就已经进行上下文转换了,这个时候访问条件转化为内部的筛选条件。
这一过程是不受人为控制的,当外部条件和内部条件同时作用一列时,内部的优先级是大于外部的。
举个例子:
代码1:
外部筛选 =
RANKX ( ALL ( '例子' ), SUM ( '例子'[销售] ) )
代码2:
转化筛选 =
RANKX ( ALL ( '例子' ), CALCULATE ( SUM ( '例子'[销售] ) ) )
表1代表的可以理解为当前上下文,原始数据中白茶特地构建了三个没有数据的日期。
表2代表的是行上下文无法转化为当前上下文,这也是为什么RANKX结果全是1的原因,因为没有取到正确的值,所以无法正确排序。
表3代表的是通过CALCULATE函数将行上下文转化为了当前上下文,即当前上下文的筛选条件对于SUM聚合生效,所以能获得每一个日期对应的数据值,因此RANKX函数生效,求出正确排名。
这个时候可以理解CALCULATE是在外部筛选,即行上下文的基础上,将其进行转化生成新的上下文,即计算上下文。
通过显性筛选可以发现并没有对CALCULATE函数的内部运算产生影响,只是单纯的起作用,影响结果的呈现。
S、屏蔽筛选
类似于ALL这类函数的屏蔽作用,可以抵消掉前两者的影响。
例子:
屏蔽筛选 =
CALCULATE ( SUM ( '例子'[销售] ), ALL ( '例子' ) )
从上图中可以看到,无论是双向筛选关系,外部筛选的行上下文和切片器,还是内部产生的计算上下文,在ALL函数面前统统是失效的。
这个时候屏蔽筛选的优先级是远远大于前三者的。
SS、表筛选
类似于FILTER或者VALUES函数这种可以生成新表的表函数,优先级大于前四者。
例子1:
表筛选1 =
CALCULATE ( SUM ( '例子'[销售] ), ALL ( '例子' ), FILTER ( '例子', '例子'[日期] <= 2017 ) )
例子2:
表筛选2 =
CALCULATE ( SUM ( '例子'[销售] ), ALL ( '例子' ), VALUES ( '例子'[日期] ) )
从上面的动图中可以看出,CALCULATE函数内部表函数生成的筛选条件,相当于自己的亲儿子,可以完全抵消掉显性筛选、外部筛选、转化筛序以及屏蔽筛选的效果,一切以它为基准。
从上述所有的示例中,我们可以判断得出,CALCULATE函数对于执行顺序,即优先级划分是遵照前面白茶描述那样进行的:
A(显性筛选)<B(外部筛选)<R(转化筛选)<S(屏蔽筛选)<SS(表筛选)
关于行上下文和筛选上下文有时候不是那么特别容易区分,一不留神就容易搞混。
对于学过编程的小伙伴来说还好,类似于作用域。但是对于像白茶这种没接触过互联网代码的人来说,理解起来真的很吃力。
嘿神是这样说的:
行上下文类似于地球,有固定的经纬度,可以按照经纬度索引查找地理位置;
而筛选上下文是划分范围,需要知道你想上哪个国家,才会告诉你怎么去;
才会告诉你那里位于南北纬东西经的位置,那里有个什么地方。
即:筛选上下文→迭代器→激活行上下文→索引取值→值运算。
好了,关于CALCULATE函数的所有内容到本期彻底告一段落了,希望能对看到这里的小伙伴有所帮助。
至于后面的CALCULATETABLE函数,其内部的优先级原理与前者差不多,白茶就不赘述了。
这里是白茶,一个PowerBI的初学者。