在计算列中使用 SUM
第一个测试很简单。如果在销售表中使用如下代码定义一个计算列将会发生什么?
Sales[SumOfSalesAmount] = SUM ( Sales[SalesAmount] )
由于计算列将会逐行计算,且对于每行将取得一个结果。你期望看到什么数字?从下列选项中任选其一:
- 对每行有特定的 SalesAmount 值,且每行各不相同。
- 每行得到的都是 SalesAmount 的总计,也就是所有行都有相同的值。
- 错误;我无法在计算列中使用 SUM,所以根本无法执行计算。
请停止阅读,做出你的判断,然后再继续阅读。
现在让我们来阐述当公式计值时都究竟发生了什么。如你所知,该公式表示:“当前筛选上下文中出现的所有销售金额的合计。”现在该公式要逐行计值,所以 DAX 为第一行创建了行上下文,然后调用该公式计值。公式对当前筛选上下文中的所有销售金额计算了合计值。那么当前筛选上下文是什么?是一个完整的数据库,因为公式并非位于任何数据透视表内计值,而是在当筛选器尚未处于活动状态,在计算列定义时的计值。
确实存在一个行上下文,但 SUM 忽略了行上下文而仅使用筛选上下文,且筛选上下文恰恰正是整个数据库。因此正确的答案是第二个:你将得到 SalesAmount 的总计值,且在销售表的所有行均有相同值,如图所示。
该例子清楚地表明了这两类上下文的共同作用。两者都对公式的最终结果起作用但方式不同。聚合函数,例如 SUM、MIN 和 MAX 感知到筛选上下文所定义的范围,并完全忽略了行上下文。如果你回答(1)是很正常的,许多学生通常也是这么选的。关键在于你还没有意识到这两个上下文共同起作用并以不同的方式改变了公式结果。回答(1)是最常见和最直观的逻辑,现在你知道为什么该答案是不对的了。
在度量值中使用列
我们要做的第二个测试略有不同。试想一下要在度量值中而非在计算列中为 Gross margin 定义公式。数据库中有一列是销售额,另一列是产品成本,你可能要在度量值中编写以下表达式:
[GrossMargin] := Sales[SalesAmount] - Sales[ProductCost]
此时你期待得到什么结果呢?
- 表达式能正常工作,我们需要在数据透视表中测试其结果。
- 报错,我甚至无法完成对公式的编写。
- 我可以定义该公式,但用于数据透视表中时就会出现错误。
和之前一样,停止阅读,思考答案,然后阅读下面的解释。
在公式中我们使用了 Sales[SalesAmount],这是一个列名(即销售表中 SalesAmount 列的值)。该定义有缺失的信息吗?你应该还记得以前的讨论:要从行中获取 SalesAmount 的当前值,这里缺失的信息恰恰就是行。当此代码用于计算列内部时,多亏了行上下文,计算该表达式时引擎隐式地定义了所使用的行。但对于度量值而言又会发生什么呢?这里既无迭代也无当前行,也就是不存在行上下文。
因此,第二个答案是正确的。你甚至不能写出公式;它在语法上是错误的,当你试图输入它时,将收到错误提示。
在度量值中指定此计算的正确方法是使用聚合函数,如:
[GrossMargin] := SUM ( Sales[SalesAmount] ) - SUM ( Sales[ProductCost] )
我们使用该公式,通过 SUM 来聚合,因此公式不考虑行上下文的存在,仅需筛选上下文就能提供正确结果。
不是忽略了行上下文,行上下文还是在那里,因为本例的筛选上下文并没有实际进行筛选,筛选上下文作用到行上下文上之后还是原来的行上下文。行上下文是原材料,忽略了原材料不就是无源之水了么?
度量值定义的时候,后面引用的列没有办法进行定位。所以才无法进行计算的?
“确实存在一个行上下文,但 SUM 忽略了行上下文而仅使用筛选上下文,且筛选上下文恰恰正是整个数据库。”,请问老师,原文里面的这句话不太明白。请问存在的行上下文是什么?而筛选上下文是什么?可以明确给说明一下吧?多谢
你好老师,我想问下关于PATH族函数的计值环境,例如下面的数据集Staffs,其中:
FullPath_c= PATH(Staffs[Name], Staffs[Team]),它是计算列
FullPath_m = [M_full_path],它也是计算列,而[M_full_path]是度量值
M_full_path := PATH(Staffs[Name], Staffs[Team])
但它们的结果是一样的,那我就不理解了,因为引用度量值会进行上下文转换,所以FullPath_c和FullPath_m 所处的计值上下文应该是不同的,但他们的结果一样,莫非内置了ALL?还是其他原因?谢谢
高飞老师,能否借用一种类似软件开发流程的“泳道图”来更直观地展示上下文转换和计值的过程吗?这部分内容看了几遍感觉有些收获,但又无法完全梳理出来
想问一下大大,这周末会更新吗?另外迭代函数的更新会到最后吗?