CALCULATE(m,x = red)与CALCULATE(m,KEEPFILTERS(x = red))之间的差异

时间:2019-09-09 08:26:05

标签: powerbi dax

CALCULATE(m, x=red)CALCULATE(m, KEEPFILTERS(x=red))有什么区别

显然它们并不相同。我找到了文档和说明,但仍然不明白。

https://docs.microsoft.com/en-us/dax/keepfilters-function-dax

https://dax.guide/keepfilters/

2 个答案:

答案 0 :(得分:4)

没有KEEPFILTERS的情况下,您的第一个度量将覆盖应用于字段x的所有其他过滤器。

第二个度量使用KEEPFILTERS维护字段x上的过滤器上下文,并将新的过滤器上下文作为现有过滤器的子集应用(或空白,如果过滤器上下文没有重叠)。 / p>

这是一个简单的PBIX文件示例,用于演示-使用颜色切片器,并查看两种测量方法的区别:https://pwrbi.com/so_57850298/

这个SQLBI.com article解释得很好。

答案 1 :(得分:2)

更多地了解如何评估CALCULATE中的简单谓词是有帮助的。以下两个表达式是等效的;实际上,第一个只是语法糖,第二个-前者在幕后被重写为后者:

CALCULATE ( [m], 'T'[Col] = "Red" )

CALCULATE (
  [m],
  FILTER (
    ALL ( 'T'[Col] ),
    'T'[Col] = "Red"
  )
)

FILTER是一个迭代器,该迭代器将表作为第一个参数,将要在行上下文中求值的谓词作为第二个参数。它将从谓词为false的输入表中删除所有行。

因此,CALCULATE对过滤器上下文的操作实际上几乎完全是对表的操作。如果您对关系代数感到满意,则CALCULATE的args2-N中的表是与CALCULATE的arg1中的表达式中要操作的表半连接的表。这些半联接取决于数据模型中定义的关系。

因此FILTER ( ALL ( 'T'[Col] ), <predicate> )的模式将忽略'T'[Col]上的任何外部过滤器上下文,并将其替换为您定义的新过滤器上下文。

现在KEEPFILTERS。我不是100%肯定这只是语法糖,但我相信是。无论哪种方式,下面的两个表达式在语义上都是等效的-它们将始终返回相同的值:

CALCULATE ( [M], KEEPFILTERS ( 'T'[Col] = "red" ) )

CALCULATE (
  [M],
  FILTER (
    VALUES ( 'T'[Col] ), // this is the only difference from the first expansion
    'T'[Col] = "red"
  )
)

您可以看到KEEPFILTERS扩展正在使用VALUES而不是ALL。因此,ALL将返回命名列中的所有唯一值,而忽略该列上的任何过滤器上下文(它还有其他形式可以在一个以上的列上进行操作,但这与本讨论无关)。 VALUES返回当前过滤器上下文中命名列的唯一值。

另一种思考方式如下。假设值“ red”确实存在于“ T” [Col]中。 FILTER ( ALL ( 'T'[Col] ), 'T'[Col] = "red" )将始终返回值为'red'的1列1行表'T'[Col]。 FILTER ( VALUES ( 'T'[Col] ), 'T'[Col] = "red" )将始终返回一个1列的表,其中包含0行或1行;如果外部过滤器上下文包含“ T” [Col] =“ red”,则它将返回具有'T'[Col] =“ red”的1行表,而如果外部过滤器上下文不包含该值,它将返回空表。

同样,以上FILTER表达式的表输出被视为左侧半联接中的右侧表。

尤其要注意,以上所有内容均基于单列。如果有多个列构成过滤器上下文,则可能会引发循环。这是一个易于理解的示例。我们定义了两个度量,并将它们放入带有'DimDate'[Year]和'DimDate'[Date]的表格中。

Prior Date = 
VAR CurrentDate = MAX ( 'DimDate'[Date] )
RETURN
  CALCULATE (
    MAX ( 'DimDate'[Date] ),
    'DimDate'[Date] = CurrentDate - 1
  )
Prior Day ALL DimDate = 
VAR CurrentDate = MAX ( 'DimDate'[Date] )
RETURN
  CALCULATE (
    MAX ( 'DimDate'[Date] ),
    ALL ( 'DimDate' ),
    'DimDate'[Date] = CurrentDate - 1
  )

这是它们在表格视觉中返回的内容:

table with year and date and the two measures

在DAX中定义了带有日期的算术,<date> - 1将始终返回先前的日期。因此,2019年1月1日的CurrentDate - 1是2018年12月31日。但是在我们的视觉效果中,我们同时具有来自'DimDate'[Year]和'DimDate'[Date]的过滤器上下文,因此在第一个度量中,我们正在'DimDate'[]的过滤器上下文中计算MAX ( 'DimDate'[Date] ) Year] = 2019和'DimDate'[Date] = 2018-12-31(CALCULATE中的上下文操作)。 'DimDate'中没有同时匹配这两个条件的行,因此第一个版本返回空白。第二个版本清除了所有来自'DimDate'的过滤器上下文,因此剩下的唯一上下文是我们在'DimDate'[Date] = CurrentDate - 1中明确应用的内容。

请注意,上面的示例仅在使用KEEPFILTERS时返回总计值。

Prior Date KEEPFILTERS = 
VAR CurrentDate = MAX ( 'DimDate'[Date] )
RETURN
  CALCULATE (
    MAX ( 'DimDate'[Date] ),
    KEEPFILTERS ( 'DimDate'[Date] = CurrentDate - 1 )
  )

KEEPFILTERS visual

这仅适用于总计,因为在详细级别,KEEPFILTERS ( 'DimDate'[Date] = CurrentDate - 1无法返回任何值。就是说,本质上是“找到一个比自己少的日期”,这显然是不可能的。但是总的来说,上下文中有许多日期,因此我们正在筛选包含许多连续日期的表。因此,我们的度量值可以返回总计值。