DAX 第六篇:上下文转换

关于计值上下文的规则:

  • 筛选上下文用于筛选数据。
  • 行上下文用于迭代,其中的筛选上下文为空,除非遇到CALCULATE函数。

一,CALCULATE函数根据行上下文创建筛选上下文

CALCULATE函数的强大之处:根据行上下文创建筛选上下文。

如果在行上下文中执行CALCULATE函数,对每一次迭代,CALCULATE函数都会把外部的行上下文转换为等价的筛选上下文,换句话说,把当前行的所有字段作为CALCULATE函数的过滤器参数,以此创建新的筛选上下文。CALCULATE函数的内部不存在外部行上下文,只有筛选上下文,也就是说,CALCULATE函数把外部的行上下文隐式转换为外部筛选上下文(等价于隐式设置过滤器参数),CALCULATE函数再根据外部的筛选上下文和过滤器参数创建自己的内部筛选上下文。

下面两个度量的结果是等价的,由于第一个表达式执行了上下文转换,性能低于第二个:

Sales Amount = SUMX ( Sales, CALCULATE( SUM(Sales[Quantity]) ) )

Sales Amount = SUMX ( Sales, Sales[Quantity]) 

注意:如果表中存在完全相同的多行,那么CALCULATE函数基于行上下文创建的筛选上下文是相同的。

二,迭代函数不会把行上下文转化为筛选上下文

在一个行上下文中,迭代函数不会把行上下文转换为筛选上下文,这就是说,对迭代函数来说,行上下文没有筛选上下文。即对于行上下文中的迭代函数来说,筛选上下文为空,不执行任何过滤。

以下计算列的计算过程是:由于迭代函数SUMX在行上下文中没有筛选上下文,因此Sales没有进行过滤,字段[Gross Sales Amount]的值是整个Sales表的Quantity字段的和。

Sales[Gross Sales Amount] = SUMX ( Sales, Sales[Quantity]) 

三,度量中的上下文转换

DAX的一个重要特性:每个被引用的度量值都被隐式封装在CALCULATE函数中,这种行为对上下文转换至关重要。由于CALCULATE函数的存在,在任何行上下文中引用度量值,都将被执行隐式的上下文转换。

举个例子,在计算列中引用度量值,计算列[Sales Amount2]和[Sales Amount3]实际上是一样的。

Sales Amount = SUMX ( Sales, Sales[Quantity]) 
Sales[Sales Amount2]
= [Sales Amount] Sales[Sales Amount3]= CALCULATE( SUMX ( Sales, Sales[Quantity]) )

但是这种写法涉及到上下文的转换,CALCULATE函数强制把行上下文转换为筛选上下文,代码运行非常低效。

推广到一般情况,DAX中有两个规则,使得行上下文转换为筛选上下文:

  • 在行上下文中调用CALCULATE函数时,行上下文会转换为筛选上下文。
  • 由于每个被引用的度量值都被隐式封装在CALCULATE函数中,在任何行上下文中引用度量(Measure)时,行上下文会转换为筛选上下文。

 举个例子,在迭代函数中引用度量时,第一个DAX公式,在DAX引擎内部,会被转换为第二个公式。MAXX是迭代行数,CALCULATE函数处于外部的行上下文中,此时,外部的行上下文会被CALCULATE函数转换为外部的筛选上下文,并根据这个外部筛选上下文和过滤器参数创建自己的内部筛选上下文,最终CALCULATE函数根据内部筛选上下文来执行计算。

Max Daily Sales= MAXX(DimDate'Date', [Sales Amout])

Max Daily Sales= MAXX(DimDate'Date'
                      ,CALCULATE(SUMX(Sales, Sales[Quantity]*Sales[Net Price]))
                 )

 

 

参考文档:

DAX overview

posted @ 2019-09-11 11:08  悦光阴  阅读(4552)  评论(0编辑  收藏  举报