03.07 计值上下文理解测试
在计算列中使用SUM
第一个测试很简单。如果在销售表中使用如下代码定义一个计算列将会发生什么?Sales[SumOfSalesAmount]=SUM(Sales[SalesAmount])由于计算列将会逐行计算,且对于每行将取得一个结果。你期望看到什么数字?从下列选项中任选其一:
- 对每个特定行有SalesAmount值,且每行各不相同。
- 对所有行得到SalesAmount的总计,所有行都有相同的值。
- 错误;我无法在计算列中使用SUM,所以根本无法执行计算。 请停止阅读,做出你的判断,然后再继续阅读。现在让我们来阐述当公式计值时都究竟发生了什么。如你所知,该公式表示:“当前筛选上下文中出现的所有销售金额的合计。”现在该公式要逐行计值,所以DAX为第一行创建了行上下文,然后调用该公式计值。公式对当前筛选上下文中的所有销售金额计算了合计值。那么当前筛选上下文是什么?是一个完整的数据库,因为公式并非位于任何数据透视表内计值,而是在当筛选器尚未处于活动状态,在计算列定义时的计值。确实存在一个行上下文,但SUM忽略了行上下文而仅使用筛选上下文,且筛选上下文恰恰正是整个数据库。因此正确的答案是第二个:你将得到SalesAmount的总计值,且在销售表的所有行均有相同值,如图所示。SumOfSalesAmount计算列基于整个数据库进行计算该例子清楚地表明了这两类上下文的共同作用。两者都对公式的最终结果起作用但方式不同。聚合函数,例如SUM、MIN和MAX感知到筛选上下文所定义的范围,并完全忽略了行上下文。如果你回答(1)是很正常的,许多学生通常也是这么选的。关键在于你还没有意识到这两个上下文共同起作用并以不同的方式改变了公式结果。回答(1)是最常见和最直观的逻辑,现在你知道为什么该答案是不对的了。# 在度量值中使用列 我们要做的第二个测试略有不同。试想一下要在度量值中而非在计算列中为Gross margin定义公式。数据库中有一列是销售额,另一列是产品成本,你可能要在度量值中编写以下表达式:[GrossMargin]:= Sales[SalesAmount]- Sales[ProductCost]此时你期待得到什么结果呢?
- 表达式能正常工作,我们需要在数据透视表中测试其结果。
- 报错,我甚至无法完成对公式的编写。
- 我可以定义该公式,但用于数据透视表中时就会出现错误。
和之前一样,停止阅读,思考答案,然后阅读下面的解释。在公式中我们使用了Sales[SalesAmount],这是一个列名(即销售表中SalesAmount列的值)。该定义有缺失的信息吗?你应该还记得以前的讨论:要从行中获取SalesAmount的当前值,这里缺失的信息恰恰就是行。当此代码用于计算列内部时,多亏了行上下文,计算该表达式时引擎隐式地定义了所使用的行。但对于度量值而言又会发生什么呢?这里既无迭代也无当前行,也就是不存在行上下文。因此,第二个答案是正确的。你甚至不能写出公式;它在语法上是错误的,当你试图输入它时,将收到错误提示。记住,列本身没有值,相反,它对于表中每行都有不同的值。因此如果想要单个值就需要指定所用的行。指定计算所用行的唯一方式是使用行上下文,因为在这个度量值内部不存在行上下文,所以该公式是不正确的,将不予接受。在度量值中指定此计算的正确方法是使用聚合函数,如:[GrossMargin]:=SUM(Sales[SalesAmount])-SUM(Sales[ProductCost])我们使用该公式,通过SUM来聚合,因此公式不考虑行上下文的存在,仅需筛选上下文就能提供正确结果。