4.2 测试您对评估上下文的理解
测试您对评估上下文的理解
在继续进行关于评估上下文的更复杂的描述之前,使用几个示例来测试您对上下文的理解是很有用的。请不要立即查看说明;在问题之后停下来并尝试回答。然后阅读说明以使之有意义。作为提示,请在思考时记住“筛选上下文筛选;行上下文进行迭代。这意味着行上下文不会筛选,并且筛选上下文不会迭代。”
在计算列中使用SUM
第一个测试使用计算列内的聚合函数。在Sales表中,计算列中使用以下表达式的结果是什么?
Sales [SumOfSalesQuantity] = SUM(Sales [Quantity])
请记住,这在内部对应于以下等效语法:
Sales [SumOfSalesQuantity] = SUMX(Sales,Sales [Quantity])
因为它是计算列,所以它是在行上下文中逐行计算的。您希望看到什么数?从以下三个答案中选择:
- 该行的“数量”值,即每行不同的值。
- 所有行的数量总计,即所有行的值相同。
- 一个错误; 我们不能在计算列内使用SUM。
请停止阅读,我们在等待您的有根据的猜测之后再继续。
这是正确的推理。您已经了解到该公式的意思是“当前过滤器上下文中所有可见行的数量之和”。此外,由于代码是针对计算列执行的,因此DAX在行上下文中逐行评估公式。但是,行上下文不会筛选表。可以筛选表的唯一上下文是筛选上下文。这就使问题变成了另一个问题:对公式求值时,筛选上下文是什么?答案很简单:筛选上下文为空。实际上,筛选上下文是通过视觉对象或查询创建的,并且当没有筛选发生时,在数据刷新时将计算出一个列。因此,SUM在整个 Sales 表上工作,为 Sales 的所有行汇总 Sales [Quantity] 的值。
正确答案是第二个答案。此计算列为每一行计算相同的值,即对所有行重复的 Sales [Quantity] 总计。图4-8显示了 SumOfSalesQuantity 计算列的结果。
图4-8 在计算列中的SUM(Sales [Quantity])是针对整个数据库计算的此示例显示两个评估上下文同时存在,但是它们不相互作用。评估上下文都对公式的结果起作用,但是它们以不同的方式起作用。SUM,MIN和MAX之类的聚合函数仅使用筛选上下文,而忽略行上下文。如果您像许多学生通常那样选择了第一个答案,那是完全正常的。事实是,您仍在混淆筛选上下文和行上下文。记住,筛选上下文筛选;行上下文进行迭代。当使用直观逻辑时,第一个答案是最常见的,但这是错误的——现在您知道为什么了。但是,如果您选择了正确的答案……那么我们很高兴本节帮助您学习了两种情况之间的重要区别。
在度量值中使用列
第二项测试略有不同。想象一下,我们在度量中而不是在计算列中定义毛利率公式。我们有一个包含净价的列,另一个包含产品成本的列,我们编写以下表达式:
GrossMargin% := ( Sales[Net Price] - Sales[Unit Cost] ) / Sales[Unit Cost]
结果将是什么?如前所述,请从以下三个可能的答案中进行选择:
- 该表达式可以正常工作,需要时间在报表中测试结果。
- 一个错误,我们甚至不应该写这个公式。
- 我们可以定义公式,但是在报表中使用时将返回错误。
与以前的测试一样,停止阅读,考虑答案,然后阅读以下说明。
该代码引用了 Sales[Net Price] 和 Sales[Unit Cost],没有任何聚合函数。因此,DAX需要检索某行的列值。因为没有迭代发生,并且代码不在计算列中,DAX无法检测需要公式计算的行,换句话说,DAX缺少行上下文,这将使得有可能将表达式的一部分作为列值检索。记住,度量值没有自动行上下文,仅计算列才有。如果我们需要度量值中的行上下文,则应该开始迭代。
因此,第二个答案是正确的。我们不能编写公式,因为它在语法上是错误的,并且在尝试输入代码时出现错误。