- 1 -


     所有对Calculate函数的疑问,几乎全都跟它的计值流有关系。


     首先,看一个群里朋友问的问题:求各菜品名称的最大日期对应的销售量。


     1、为什么先写好度量[最大日期],然后在Calculate的筛选条件里调用,却不能得到正确的结果呢?filter是行上下文应该不具备筛选功能?


Calculate计值流,DAX最重要知识点,没有之一!【兼5月送书福利】_类函数


       因为在行上下文环境里引用度量,会进行行上下文转换,所以,上面filter里的[最大日期]将与第一个参数Values()里的值一一对应,最终导致该filter的筛选条件永远是true。


      2、为什么用max却能得到正确的结果?max('事实表'[日期])不是计算整张表的最大日期吗?


Calculate计值流,DAX最重要知识点,没有之一!【兼5月送书福利】_筛选器_02


       这里关键要理解Calculate函数的的计值流,它的filter参数,会在现有的计算上下文(如这里的“菜品名称”筛选上下文)中进行计算,所以,max会取到当前“菜品名称”下的最大日期,最终得出正确答案,如下图所示:


Calculate计值流,DAX最重要知识点,没有之一!【兼5月送书福利】_筛选器_03


- 2 -


       参考DAX圣经,总结Calculate函数计值流如下,建议收藏随时回查!哪怕还不理解,也先熟悉起来!哪怕背100遍,也要背下来!后面我也会用更多的例子给大家一点点讲。


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 生成的筛选上下文中计值第一参数。


Calculate计值流,DAX最重要知识点,没有之一!【兼5月送书福利】_类函数_04