从数据到信息
从信息到洞察

计值上下文测试

在计算列中使用 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]

此时你期待得到什么结果呢?

  1. 表达式能正常工作,我们需要在数据透视表中测试其结果。
  2. 报错,我甚至无法完成对公式的编写。
  3. 我可以定义该公式,但用于数据透视表中时就会出现错误。

和之前一样,停止阅读,思考答案,然后阅读下面的解释

在公式中我们使用了 Sales[SalesAmount],这是一个列名(即销售表中 SalesAmount 列的值)。该定义有缺失的信息吗?你应该还记得以前的讨论:要从行中获取 SalesAmount 的当前值,这里缺失的信息恰恰就是行。当此代码用于计算列内部时,多亏了行上下文,计算该表达式时引擎隐式地定义了所使用的行。但对于度量值而言又会发生什么呢?这里既无迭代也无当前行,也就是不存在行上下文。

因此,第二个答案是正确的。你甚至不能写出公式;它在语法上是错误的,当你试图输入它时,将收到错误提示。

记住,列本身没有值,相反,它对于表中每行都有不同的值。因此如果想要单个值就需要指定所用的行。指定计算所用行的唯一方式是使用行上下文,因为在这个度量值内部不存在行上下文,所以该公式是不正确的,将不予接受。

在度量值中指定此计算的正确方法是使用聚合函数,如:

[GrossMargin] := SUM ( Sales[SalesAmount] ) - SUM ( Sales[ProductCost] )

我们使用该公式,通过 SUM 来聚合,因此公式不考虑行上下文的存在,仅需筛选上下文就能提供正确结果。

5
说点什么

avatar
1000
 
鼓掌微笑开心憧憬爱你色并不觉得吃瓜doge二哈喵喵思考笑哭捂脸悲伤大哭抓狂汗偷笑打脸捂眼黑线问号晕拜拜闭嘴衰咒骂ok作揖
1 评论数
4 被回复的评论
1 订阅评论的人数
 
查看最近回复
查看最热评论
  订阅本文评论  
最新 最旧 得票最多
提醒
李星棋
成员
李星棋

想问一下大大,这周末会更新吗?另外迭代函数的更新会到最后吗?