从数据到信息
从信息到洞察

CALCULATE 指南

本文是 CALCULATE 系列的最后一篇,是时候提供关于这个函数全面总结了。之后你在浏览其他文章的时候,很可能会多次回来参考本文的内容,不必担心,这是正常的。每当需要回忆 CALCULATE 的复杂行为时,你都可以在这里找到答案。

不要因为反复查看本文内容而怀疑自己的学习能力,即使一些使用 DAX 多年的开发者,仍然必须提醒自己注意公式的计算规则。DAX 是纯净且强大的语言,但一些容易被遗忘的细节往往能解决特定场景下的关键问题。

CALCULATE 总结

初始环境

CALCULATE计值上下文中执行,该上下文包含一个筛选上下文,可能包含一个或多个行上下文,这是公式计值的初始环境。

创建新的筛选上下文

CALCULATE 创建一个新的筛选上下文,在其中计值第一个参数。新的筛选上下文只包含筛选上下文,由于上下文转换的作用,所有行上下文在筛选上下文中都消失了。

接受三种参数

CALCULATE 表达式接受三种类型的参数:

第一参数必选,将在新筛选上下文中计值的表达式。

显式筛选器参数:用来操作原始筛选上下文,每个筛选器参数都可能使用参数调节器(Modifier),比如 KEEPFILTERS

CALCULATE 调节器:通过删除一些筛选器或更改关系结构,可以修改模型、调整初始筛选上下文的范围。

执行上下文转换

当原始上下文包含一个或多个行上下文时,CALCULATE 执行上下文转换,向上下文堆栈中添加不可见的隐式筛选器。默认情况下这些隐式筛选器会覆盖外部上下文提供的筛选器,而如果提供行上下文的是使用 KEEPFILTERS 的表表达式,这种情况下隐式筛选器的行为也会被 KEEPFILTERS 修改。

CALCULATE 计值流

CALCULATE 遵循一个非常精确的算法来使用所有的参数。当你需要理解某些复杂计算的时候,必须很好地理解这种算法:

  1. CALCULATE 在初始计值上下文环境中的计算所有显式筛选器参数
    初始上下文是公式外部环境,包括原始行上下文(如果有的话)和原始筛选上下文。所有显式筛选器参数在这个初始环境中独立计算,计算完成后,CALCULATE 开始构建新的筛选上下文。
  2. CALCULATE 复制原始筛选上下文,以准备新的筛选上下文
    这个过程中会丢弃原始行上下文,因为新的计值上下文将不包含任何行上下文。
  3. CALCULATE 执行上下文转换
    CALCULATE 使用列在原始行上下文中的当前值,为正在迭代的所有列提供一个具有唯一值的筛选器。值得注意的是此筛选器可能包含也可能不包含单个行,因为上下文转换并不保证新的筛选上下文只包含一行。如果没有正在生效的行上下文,则跳过此步骤。一旦上下文转换创建的所有隐式筛选器都应用于新的筛选上下文,计算就进入步骤 4。
  4. 计算调节器函数 USERELATIONSHIP、CROSSFILTER 和 ALL 类函数
    这个步骤发生在步骤 3 之后。这非常重要,意味着我们可以通过使用 ALL 来消除上下文转换的影响。CALCULATE 调节器在上下文转换之后应用,因此可以更改上下文转换的效果。
  5. CALCULATE 将步骤 1 的结果应用于步骤 4 之后生成的新筛选上下文
    一旦发生了上下文转换,这些筛选器参数就会应用到新的筛选上下文中覆盖转换生成的上下文。这个过程发生在步骤 4 之后,也就是 ALL 系列函数移除上下文和模型关系结构更新之后,所以这一步生成的上下文不会被 ALL 影响。同时,筛选器参数的计算发生在原始筛选上下文中,不受同一 CALCULATE 中任何其他调节器或筛选器的影响。

最终,CALCULATE 在步骤 5 生成的筛选上下文中计值第一参数。

83
说点什么

1000
 
鼓掌微笑开心憧憬爱你色并不觉得吃瓜doge二哈喵喵思考笑哭捂脸悲伤大哭抓狂汗偷笑打脸捂眼黑线问号晕拜拜闭嘴衰咒骂ok作揖
25 评论数
65 被回复的评论
12 订阅评论的人数
 
查看最近回复
查看最热评论
  订阅本文评论  
最新 最旧 得票最多
提醒
游客
13910953194

老师,如果既有外部筛选上下文,又发生行下文转换,cal内部筛选参数前有修改器,请问修改器修改发生了几次?我理解行上下文发生转换后,修改器修改了转换后的筛选上下文,这里的转换后的筛选上下文应该是和初始筛选上下文发生了覆盖,同列得话,转换筛选覆盖初始筛选,对吗?
同时,初始筛选文跟内部筛选参数作用,作用前又一次被修改器修改,被修改后再跟筛选参数作用?修改器这里用了2次?

游客
lily

老师,网站何时有新内容?

成员
lily

“这个步骤发生在步骤 3 之后。这非常重要,意味着我们可以通过使用 ALL 来消除上下文转换的影响。”

老师,以上描述不够严谨吧?如果有初始筛选和行上下文转换后的筛选上下文环境并存,all就近调节与all里面的第一参数同列的筛选器,但如果没有行上下文转换发生,all调节的是初始筛选上下文同列吧?

另,既然是 cal的计值流,我认为不应该把 “1.CALCULATE 在初始计值上下文环境中的计算所有显式筛选器参数” 放置在第一步,真正的第一步应该是 “CALCULATE 复制原始筛选上下文,以准备新的筛选上下文”,

还有,第5步:“CALCULATE 将步骤 1 的结果应用于步骤 4 之后生成的新筛选上下文”,应该是在调节器调节后的动作发生后,(调节器调节的可能是初始筛选上下文,也能是行上下文转换后的筛选上下文,如果两个上下文都存在或发生,则优先调节行上下文转换后的筛选上下文,且为同列的筛选器),第5步,应该是:这些筛选上下文和cal 内部的筛选器分别独立计算形成最终的筛选上下文。 您认为呢?

成员
lily

老师,几次翻看了评论,重复实践计值的顺序,您看这次理解是否ok?

总结说来,从外层到内层(从初始->上下文转换->调节器->显示筛选器),内层影响外层。这里影响是指覆盖(替换)、增加或删除或交集或并集。

如果一个度量值既由外部筛选上下文,也有内部筛选器,计算顺序如下:
step1: 外部筛选上下文 先发生复制,就此等待,假设存放在变量var1里;
step2:行上下文遇cal转换筛选上下文,假设存放在变量var2里;
step3: 假设存在all调节器,且all第一参数为一个筛选器,注意,高老师之前评论说过,调节器只调节一次,但这里我不清楚的是就近调节var2? 还是var1?还是调节var2和var1作用后生成的新变量var3上下文? 还是调节var1或var2里有共同列的其中一个变量? 还是仅仅就是调节var2,如果var2里没有相同列,则该调节器不发生作用,等同无此调节器?
step4: step3后生成的调节后的筛选上下文和cal里的显示筛选器,假设3个显示筛选器(这里包括all调节器的第一参数筛选器),分别各自独立发生作用(交集、覆盖或并集等),形成变量var4上下文。
step5:变量var4代表的筛选上下文和var1(外部初筛筛选上下文)相互作用后形成最终的筛选上下文呢?还是 初始筛选上下文var1和行上下文转换的筛选上下文var2,两者共同作用生成另外的筛选上下文,然后被后面的all调节器调节,调节后的筛选上下文和内部的三个筛选器分别独立作用,最后交集生成最终的筛选上下文呢?

老师,麻烦您重点解答下step3和step5,多谢啦。

游客
13820507101

请您删除我(13820507101)所有的阐述和评论,我不想背刷屏之名。对Dax的理解和叙述,我不能以一两句话概括,目的是让学友想通。

我昨天已经逐条给您发申请了,请删除我在这个坛子的所有阐述和评论。

谢谢!

成员
139****3194

老师,既有外部筛选文上下文,也发生行上下文转换筛选上下文,也有调节器keepfilters,调节器里有显示筛选器参数,且跟行上下文转换筛选上下文为同一列字段名,另在calculate 里还有另一个显示筛选器,其它的筛选上下文为不同列值表,他们计值顺序:
1. 行上下文转换筛选上下文;keepfilter保留筛选上下文;
2. 外部筛选上下文和内部显示筛选器及第1部筛选取并集.

老师,麻烦指正,谢谢。

————————–

游客
13820507101

好吧。calculate 计值流的次序是原则问题。dax.guide 阐述的第一步非常明确。不能被调序。将第一步的结果应用于哪一步也非常明确。

calculate 计算所有显式筛选器参数(返回 calculate create 显式筛选上下文)发生在第一步,是因为原始计值上下文还在。t计算的结果即显式筛选上下文,显示筛选上下文拥有最高precedence,所以它并不先应用。这个结果可以储存在变量里,或者通过什么形式保存起来。

在calculate modifier 对新筛选上下文某列移除后,calculate在最后步骤调用并应用显示筛选上下文,对calculate modifier 应用后的新筛选上下文,行使最高precedence,进行相关列替换或增加,形成最后的新筛选上下文。

老师的第四步是这样描述的:

“CALCULATE 在初始计值上下文环境中计算所有显式筛选器参数
CALCULATE 将这一步的结果应用于步骤 3 之后生成的新筛选上下文。一旦发生了上下文转换,这些筛选器参数就会应用到新的筛选上下文中覆盖转换生成的。”

这说不通。也没讲明白。
“CALCULATE 在初始计值上下文环境中计算所有显式筛选器参数”到底是在哪一步,是在步骤3之后?说不通,因为此刻初计值上下文已经不在了,或者说在堆栈下面了,再被调用?这个次序是逆行的。老师虽然将显示筛选器参数的计算和应用其结果 放在一起,看上去非常合理,但仔细推敲后,反倒是dax.guide 里的次序最合理。

回过头来,再看老师的综述:
“ 综述:CALCULATE 在初始计值上下文环境中的计算所有显式筛选器参数。初始上下文是公式外部环境,包括原始行上下文(如果有的话)和原始筛选上下文。所有显式筛选器参数在这个初始环境中独立计算,计算完成后,CALCULATE 开始构建新的筛选上下文。” 不知道是我的理解有问题,这只是在讲 CALCULATE create new explicit filter context .没有谈及 apply the result . 而这个apply the result 才是创建新筛文的闭环。这又怎能作为综述呢。

不管怎样。谢谢老师的耐心和指导。🙏

游客
13820507101

我的建议: 第四步, “ CALCULATE 在初始计值上下文环境中计算所有显式筛选器参数” 加粗黑体字做为第四步概要/标题,容易引起误导吧? 这一步是 :CALCULATE 把在初始计值上下文环境中被计值的显式筛选器参数应用于步骤3之后的新筛选上下文。 另外,综述应该是提纲挈领… 阅读更多 »

游客
13820507101

CALCULATE 表达式接受三种类型的参数:

第一参数:必选,将在新筛选上下文中计值的表达式。

显式筛选器参数:用来操作原始筛选上下文,每个筛选器参数都可能使用调节器(Modifier),比如 KEEPFILTERS。

CALCULATE 调节器:通过删除一些筛选器或更改关系结构,可以修改模型、调整初始筛选上下文的

————————–
二三类型并不MECE吧。

游客
13820507101

CALCULATE 在计值上下文中执行,该上下文包含一个筛选上下文,可能包含一个或多个行上下文,这是公式计值的初始环境。
—————————————————/
我想不出这种情况是什么:既有外部筛选上下文。同时又有一个或多个外部行上下文。都是外部。
哪种情形是这个样子的?

还是我的理解错了,行上下文指的是 迭代函数创建的行上下文? 如sumx(表,calculate())

可见的同时具备外部行上下文与外部筛选上下文的环境不存在?

成员
xifeng

老师,能帮我看下下图里的计值流程吗,当CALCULATE内部的多个筛选器不是对同一列进行筛选的时候我能理解,但是当内部的多个筛选器以及外部的筛选器都是对同一列进行筛选的时候,我就有些难以理解了。

1、在内外部筛选器都是筛选同一列的情况下,内部筛选器应该是要覆盖外部筛选器的,但是有多个内部筛选器时,所有的内部筛选器都要覆盖外部筛选器吗?然后内部筛选器再相交?

2、在有多个内部筛选器且内外部筛选器都是筛选同一列的情况下,若某个内部筛选器还使用了KEEPFILTERS将覆盖改成了相交,那么此时,内部筛选器与外部筛选器之间,是先相交还是先覆盖?,处理完外部的筛选器后,内部筛选器再相交?

今天被这个问题折磨的有点厉害,我所理解的DAX理论体系竟然不能解释这个问题 捂脸

2.jpg
成员
180****3919

老师,我使用这个例子按计值流理解一下看看有没有问题;
假如外部有个【颜色】做行标签;
Test :=
CALCULATE (
SUM ( ‘销售明细'[下单数量] ),
FILTER (
ALL ( ‘销售明细’ ),
‘销售明细'[出库日期]
= MAX ( ‘销售明细'[出库日期] )
)
)
1、复制原始筛选上下文;——复制【颜色】筛选器A
2、calculate上下文转换;—–没有行上下文,跳过
3、计算调节器函数—–ALL(表)忽略所有的筛选器,忽略步骤1的筛选器A;如果有步骤2,步骤2上下文也会被覆盖;
4、在初始上下文中计算所有显式筛选器——“初始环境”目前只有筛选器A,在筛选器环境下,计算max(日期),获得filter筛选表;
5、生成计值的最终上下文,计算第一参数;—–在步骤3的筛选器条件下,计算对象是步骤4的筛选表,按第一参数计算出结果;

成员
qingkou55

老师,您上面5个步骤中第一点是对整个步骤的综述还是就是步骤的第一步?
另外下面两点也麻烦您澄清一下:
用到的上下文环境:calculate外部筛选上下文A,calculate行上下文转换B,calculate内部筛选器(不含调节器)C,calculate调节器D:
1、显式筛选器包含外部筛选上下文A、行上下文转换的隐式筛选器B和calculate内部筛选器C还是只是A和B或A和C两部分?
2、calculate有调节器D存在时,计算顺序怎样?calculate内部筛选器C计算了几次?
我的两个理解如下,不知哪个是对的,还是都不正确:
——1)calculate内部筛选器C在外部筛选上下文A和行上下文转换的隐式筛选器B基础上生成新的筛选上下文E(E为A、B、C交集),调节器D对E进行调节生成F,calculate内部表达式在F上下文中计算;
——2)外部筛选上下文B和行上下文隐式筛选器B生成新的筛选上下文E(E为A、B交集),calculate 调节器D对E进行调节生成F,calculate内部筛选器C在F基础上取交集生成G,calculate内部表达式在G基础上计算。
谢谢!

成员
139****3194

还有下面这段太复杂了:

5. CALCULATE 在初始计值上下文环境中计值所有显式筛选器参数。将它们的结果应用于步骤 4 之后生成的新筛选上下文。

意思是:初始筛选上下文(含上下文转换)跟cal内部筛选器发生作用前,如果cal里有调节器,这时会调节初始的筛选上下文,(例如All类函数,取消其某些字段列的筛选),调前后的初始筛选上下文再和cal内部筛选器发生作用(交集或覆盖)?

谢谢老师

成员
139****3194

谢谢老师,您中的一句:一旦上下文转换创建的所有隐式筛选器都应用于新的筛选上下文,计算就进入步骤 4。

4. 计算调节器函数 USERELATIONSHIP、CROSSFILTER 和 ALL*(ALL 类函数)。这个步骤发生在步骤 3 之后。这非常重要,意味着我们可以通过使用 ALL 来消除上下文转换的影响。CALCULATE 调节器在上下文转换之后应用,因此可以更改上下文转换的效果。

意思:调节器如果采用all 函数,上下文转换创建的所有隐式筛选器将起不到筛选作用吗?

成员
139****3194

计值上下文进入堆栈(生效)的先后顺序是先外部,再上下文转换,最后是内部创建的筛选条件。这是他们计算的顺序。
如果他们都作用同一列,谁的作用更强呢? 是否倒过来,内部筛选条件最大,其次上下文转换,然后外部筛选上下文?多谢老师。

成员
139****3194

老师,请问:
– 初始环境包含筛选上下文和行上下文。如果行上下文没有条件发生转换,且calculate公式里也没有调节器,这时的计值顺序:公式外部的筛选上下文和cal 内部的筛选器共同作用(交集或覆盖)产生新的筛选上下文,对吗?
– 如果初始环境,既有外部筛选上下文,行上下文也发生了筛选转换,请问这时他们和 cal计值顺序是怎样的?先是 行上下文转换后的筛选上下文和外部的筛选上下文发生交集或覆盖,然后再和公式内部的筛选器发生计算吗? 还是外部筛选上下文和公式内部筛选器先计算,然后,行上下文转换后的筛选上下文最后和刚才前面计算的筛选器发生作用,形成最终的筛选器?

谢谢。

成员
wuleiyuan

”新的筛选上下文只包含筛选上下文,由于上下文转换的作用,所有行上下文在筛选上下文中都消失了。“,行上下文转化成筛选上下文。怎么会消失了。。假如有一个10行1列的表,基数是3,那么它就是转化成了 3个条件的筛选,高老师不知地我理解对不,如果不对能解释下吗?谢谢

DAX 圣经

导读

初识 DAX

DAX 基础知识

DAX 原理

DAX 高级原理

基础函数类型

迭代函数

CALCULATE 函数

CALCULATE 调节器

基础表函数

条件判断函数

查找匹配函数

时间智能函数

统计类函数

投影函数

分组/连接函数

集合函数

其他函数