CALCULATE函数的作用就是修改上下文, 其在未嵌套在KEEPFILTERS函数中时, 其修改方式会遵循两种规则:
准则一:如果列(或表)不在筛选器上下文中,则将向筛选器上下文添加新的筛选器来计算表达式( 取交集 )
准则二:如果列(或表)已在筛选器上下文中,则新筛选器将覆盖现有筛选器以计算表达式( 覆盖 )
关于CALCULATE函数内外筛选器交互过程的文章已经写过两篇了,在这里:
在加入ALL函数后,CALCULATE函数内外筛选器的交互过程
今天这篇文章来看看在CALCULATE函数中加入KEEPFILTERS函数后,其内外筛选器的交互会发生什么变化?
两张很简单的表:学生表及成绩表,学生表记录了学生的信息,包括姓名,性别及地区,成绩表记录了两个学期的学生成绩。

将城市和以下度量值拖入视觉对象表格中,可以看到结果如下:
度量值如下:
keepfilters.all.Score =CALCULATE (SUM ( '成绩表'[成绩] ),KEEPFILTERS (FILTER (ALL ( '学生表'[城市] ),'学生表'[城市] = "北京")))

我们看到结果表中只计算了北京地区的成绩,其他地区的成绩呢?
还是老套路,我们想象一下PowerBI内部的处理过程:
1. 迭代

PowerBI会迭代所有的城市,首先碰到的是上海,此时为行上下文
2. 执行CALCULATE函数
2.1 执行行上下文转换
将行上下文: 上海,变成筛选器: 上海
2.2 执行CALCULATE函数时,先计算筛选器参数即KEEPFILTERS函数,再执行KEEPFILTERS函数之前会先计算FILTER函数,在计算FILTER函数之前,会先计算ALL函数(哇,这有点罗哩叭嗦的…)
简单一点:
FILTER函数使得列:城市上的筛选器只剩:北京
若没有KEEPFILTERS函数,此时应该要生成新的上下文了,其方式有两种(取交集或者覆盖),在该示例中有ALL函数存在,所以该方式仅仅是覆盖,即结果应该是所有的地区的成绩都是北京地区的成绩(见下图)。

但是,因为有KEEPFILTERS的存在,所以它会改变生成新的上下文的方式:全部都变为取交集, 而且在这过程中也影响到了ALL函数的作用,这里ALL函数好像不起作用了
2.3 确定新的上下文
在上个步骤中,我们分析KEEPFILTERS改变了CALCULATE函数修改上下文的方式,变为全部取交集:
北京 和 上海 取交集 肯定为空啊,等等
3. 依次迭代所有城市,最终只有北京被计算出了成绩,生成结果如下:

CALCULATE函数修改上下文的方式有2种:或覆盖或取交集,但是 KEEPFILTERS函数将修改上下文的方式全部变为一种:取交集
KEEPFILTERS函数中筛选器参数不会影响已经存在的筛选器,比如示例中的ALL函数,按理说ALL清除列上已经存在的筛选器,但是在本例中,因为ALL函数嵌套在KEEPFILERS函数中,所以ALL并没有清楚列上已经存在的筛选器。
以上就是本人对于在加入KEEPFILTERS函数后,CALCULATE函数内外筛选器交互的理解
https://docs.microsoft.com/en-us/dax/keepfilters-function-da




