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

初识筛选上下文

任何 DAX 表达都是在上下文中计算的。上下文是公式计值的“环境”,也就是说,公式的结果始终受到环境的影响。总有两种上下文,它们分别是:筛选上下文和行上下文,统称为计值上下文

随着你对 DAX 了解的深入,会逐渐了解到“环境”和“上下文”都有着丰富的内涵,让我们先从最简单的概念开始,这篇文章让我们来认识筛选上下文

第一印象

思考这样一个非常简单的度量值:

[Sales Amount] := SUMX ( Sales, Sales[Quantity] * Sales[UnitPrice] )

你已经知道这个公式计算的内容:销售表中所有数量乘以价格的总和。你可以将这个度量值放在数据透视表中查看结果,如图所示。

不含上下文的销售金额显示了总计值

这个数字看起来平淡无奇。但是,如果你仔细想想,这个公式精确地计算了它应该计算的东西:所有销售额的总和,现在它只是一个数字。当我们使用一些列来分割它并开始深入研究时,这个数据透视表就开始变得有趣了。例如,你可以使用产品颜色列,将其放在行上,然后透视表马上就显示了一些有趣的业务信息。

销售额的总和按颜色切片

总计仍然存在,但现在它是一些更小的值的总和,每一个值,连同所有其他值,都有明确的意义。但是,如果你再仔细考虑一下,你应该注意到这里发生了一些奇怪的事情:公式没有按我们所要求的方式计算。

理解计值环境

我们假定这个公式的含义是“所有销售额的总和”。但在透视表的每个单元格中,公式并未计算所有销售额的总和,它只计算具有特定颜色的产品销售额的总和。然而,我们从未指定计算必须在数据模型的子集上发生。换句话说,该公式没有被指定是否可以处理数据的子集。

为什么公式在不同的单元格中计算不同的值?答案的确很简单:是因为 DAX 在计值表达式时所处的上下文环境。你可以把一个公式的上下文环境看作是 DAX 计算公式时所在的单元格周围的区域。

因为产品颜色位于行上,所以数据透视表中的每一行都只能看到,在整个数据库中,该特定颜色的产品子集。这是公式的周围区域提供的上下文环境,即在公式计算之前应用于数据库的一组筛选器。当公式计算所有销售金额的总和时,它不会在整个数据库中计算它,因为它无法查看所有行。当 DAX 计算产品颜色值为白色的行所使用的公式时, 只有白色产品是可见的,因此, 它只考虑与白色产品相关的销售。所以对于所有销售额总和这个度量值,当计算透视表中只显示白色产品的行时,就变成了所有白色产品销售额的总和。

公式唯一按定义方式运行的情形发生在汇总行上。在这个级别,因为没有进行筛选,所以整个数据库都是可见的

另一个示例,图中红色单元格计值的影响因素:

影响红色单元格公式计值的环境因素

任何 DAX 公式都会指定计算,但 DAX 的计算发生在计值上下文中,而上下文定义了被计算出的最终结果。公式始终相同,但结果不同,因为 DAX 根据不同的数据子集执行计算。

简单起见, 下面的示例使用了数据透视表。你也可以使用查询或在 Power BI 报表环境中定义筛选上下文,你将在后续文章中详细了解。现在,我们只使用最简单的案例,只考虑数据透视表,以便对概念有一个简化和直观的理解。

案例扩展

继续最初的案例,现在让我们把年份放在列上, 使数据透视表内容更加丰富。

销售额的总和现在被颜色和年份切片

我们已经明确了计算规则:即使公式总是相同,每个单元格都可以有不同的值,因为对透视表行和列的选择都影响了上下文。事实上,2008 年白色产品的销售额与 2007 年白色产品的销售额有所不同。而且,由于可以在行和列中放置多个字段,所以其实是行上的字段集和列上的字段集共同定义了筛选上下文。下图更加明显地说明了这一点。

行和列上的字段集共同定义了上下文环境

每个单元格有不同的值,因为行标签上有两个字段,颜色和品牌名称。行和列上的整个字段集定义了上下文。例如,上图中突出显示的单元格的上下文对应了黑色、Contoso 品牌和日历年 2007。

字段是在行上还是列上(或切片器和/或页面筛选器,或你可以通过查询创建的任何其他类型的筛选器)并不重要。所有这些筛选器都共同定义一个上下文,DAX 用其来计算公式。将字段放在行或列上只有视觉上的不同,对 DAX 的计值方式没有任何影响

让我们看看这个案例现在的全貌。我们在切片器上添加了产品类别, 并在筛选条件下的月份名称中选择了 12 月。

在典型的报告中,上下文以多种方式定义,包括切片器和筛选器

小结

有一点很清楚:每个单元格中计算的值都有一个由行、列、切片器和筛选器定义的筛选上下文。所有这些筛选条件都共同定义了上下文环境 DAX 在公式计值之前将上下文应用到模型中。此外,重要的是要知道不仅是值,而且在字段方面,不是所有的单元格都有相同的筛选器集合。例如,列上的总计只包含类别、月份和年份的筛选器,但不包含颜色和品牌的筛选器。颜色和品牌的字段在行上,它们不筛选总计。这同样适用于数据透视表中的颜色分类汇总:对于这些单元格,制造商字段没有筛选器,来自行的唯一有效筛选器是颜色。

我们将这种上下文称为筛选上下文, 顾名思义, 它是筛选表的上下文。任何你编写的公式根据(DAX 用于执行其计算的)筛选上下文的不同,都将具有不同的值。这种行为虽然非常直观, 但仍需要很好的理解。

Power BI 报表中的筛选上下文

现在你已经了解了什么是筛选上下文,所以下面的 DAX 表达式应该被理解为“在当前筛选上下文中可见的所有销售额之和”:

[Sales Amount] := SUMX ( Sales, Sales[Quantity] * Sales[UnitPrice] )

稍后你将学习如何读取、修改和清除筛选上下文。到目前为止,对以下事实有充分的了解就足够了:对于透视表的任何单元格或报表/查询中的任何值,始终存在筛选上下文。想要理解 DAX 如何计算一个公式,你总是需要考虑筛选上下文

在报表环境中创建的筛选上下文还有一个名称,叫做查询上下文,Query Context,在早期的文档中比较常见,大多数情况下我们不必做如此严格的区分

创建筛选上下文的方式

从前面的例子你已经了解到创建筛选上下文最常用的一种方式,通过透视表、可视化图表、切片器和筛选器创建筛选上下文。 

本文隐藏内容查看价格为2G币,请先
单独购买的内容长期有效,不受时间限制(购买前先刷新当前页面)。加入VIP会员可享受全站权益,性价比更高。

计算列中的筛选上下文环境

上面介绍的都是报表页环境中的筛选上下文,其实,还有一处我们经常使用但是容易忽略的环境,就是计算列中的筛选上下文。 

本文隐藏内容查看价格为2G币,请先
单独购买的内容长期有效,不受时间限制(购买前先刷新当前页面)。加入VIP会员可享受全站权益,性价比更高。

样例文件说明

DAX 圣经第一版案例使用官方的 Contoso 数据库,你可以从这里直接下载。书中的原理部分虽然没有提供示例文件,你可以使用下载的文件进行练习。

 

33
说点什么

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

原文小结有句话;“颜色和品牌的字段在行上,它们不筛选总计。”请问老师这句话怎么理解,grand total中的筛选上下文不是包含这两个字段吗?

成员
见路不走

我来吐槽一下上下文,先把这个最初翻译这个字的人拉过来枪毙5分钟,不能更简洁明了地翻译一下吗?非要给大家的学习设置障碍,你说一篇文章中的某个词、某句话要考虑上下文去理解它的意思这样大家都好理解,到了power bi哪来的上下文???
翻译成条件不好吗?一切计算的结果都是根据条件来的,这样多简洁明了。

游客
lwyzxx

老实说直接看拓展表比看这个解释要清晰简单很多,本质就是沿着关系自动拓展成了宽表,在这个宽表的基础上对列进行了筛选。
因为产品颜色位于行上,所以数据透视表中的每一行都只能看到,在整个数据库中,该特定颜色的产品子集。这是公式的周围区域提供的上下文环境,即在公式计算之前应用于数据库的一组筛选器。当公式计算所有销售金额的总和时,它不会在整个数据库中计算它,因为它无法查看所有行。当 DAX 计算产品颜色值为白色的行所使用的公式时, 只有白色产品是可见的,因此, 它只考虑与白色产品相关的销售。所以对于所有销售额总和这个度量值,当计算透视表中只显示白色产品的行时,就变成了所有白色产品销售额的总和。

成员
凡星流动

看了半天,感觉使用“集合”和“指针”来去解释会更加容易懂一点

成员
Swallow314

请问老师,我付费了但是怎么显示下载错误?谢谢

成员
xifeng

老师,能帮我看下下面这个结果的原因吗,万分感谢!!

我的疑问:矩阵的行标签不应该只是筛选单列的么,根据我的观察,下图矩阵中的行标签把相同表的索引列也设置了一个筛选器。

3.jpg
1.jpg
成员
CatCatLa

你好,老师,请问”计算列中没有任何外部筛选上下文,公式总是在整个数据库环境下计值“的意思是:因为计算列在数据表刷新时计算,而内存中表刷新时是不会有任何筛选器的,因此计算列的上下文是整个数据库环境。这样理解对吗?

成员
Jack S

老师,读完后,我的认知是:
1. DAX 表达式是始终在计值上下文中计算
2. 筛选上下文决定了,所引用列用来计算的行,以此限定了用于计算的数据库子集。然后执行计算
3. DAX 表达式必须有筛选上下文,当筛选上下文是空,计算集合是整个数据库全集,当不为空,根据筛选条件决定模型数据库子集
4. 我所直观看到的,切片器,数据透析表和表以及其他视觉对象的行列轴,视觉对象和页面筛选器 和calculate/calculatetable 内的filter argument 都是筛选上下文,它们以and 形式共同定义了引用列的哪些行需要计算,也就是用于计算的数据库子集。

成员
Jack S

在计算列中,calculate是可以的改变上下文?我实现了下,结果是,用calculate(sum(),filter),筛选后,是计算了子集,但是确是,每个子集中,每行对应得值,不知所以然

游客
13910953194

老师,图例也可以作为切片器吗?例如能被selectedvalue 取值?谢谢

成员
159****1108

请问高老师,您说“计算列中没有任何外部筛选上下文,公式总是在整个数据库环境下计值”,但是为什么又在“提示”当中说“因为随着你学习了 CALCULATE 和上下文转换的知识后,计算列的筛选上下文可以变的非常复杂”?我想问的是,在计算列中到底有没有筛选上下文环境呢,如果有的话该怎么创建呢?

成员
Kobe

我的会员是过期了吗?每次都要看充值才能看隐藏内容

成员
158****3828

相应的数据有吗,实操一遍加深理解

成员
pleasureyuer

“计算列中的没有任何外部筛选上下文,公式总是在整个数据库环境下计值”
这句话不太通顺,建议改一下,计算列中没有任何外部筛选上下文,公式总是在整个数据库环境下计值

DAX 圣经

导读

初识 DAX

DAX 基础知识

DAX 原理

DAX 高级原理

基础函数类型

迭代函数

CALCULATE 函数

CALCULATE 调节器

基础表函数

条件判断函数

查找匹配函数

时间智能函数

统计类函数

投影函数

分组/连接函数

集合函数

其他函数