任何 DAX 表达都是在上下文中计算的。上下文是公式计值的“环境”,也就是说,公式的结果始终受到环境的影响。总有两种上下文,它们分别是:筛选上下文和行上下文,统称为计值上下文。
随着你对 DAX 了解的深入,会逐渐了解到“环境”和“上下文”都有着丰富的内涵,让我们先从最简单的概念开始,这篇文章让我们来认识筛选上下文
第一印象
思考这样一个非常简单的度量值:
[Sales Amount] := SUMX ( Sales, Sales[Quantity] * Sales[UnitPrice] )
你已经知道这个公式计算的内容:销售表中所有数量乘以价格的总和。你可以将这个度量值放在数据透视表中查看结果,如图所示。
这个数字看起来平淡无奇。但是,如果你仔细想想,这个公式精确地计算了它应该计算的东西:所有销售额的总和,现在它只是一个数字。当我们使用一些列来分割它并开始深入研究时,这个数据透视表就开始变得有趣了。例如,你可以使用产品颜色列,将其放在行上,然后透视表马上就显示了一些有趣的业务信息。
总计仍然存在,但现在它是一些更小的值的总和,每一个值,连同所有其他值,都有明确的意义。但是,如果你再仔细考虑一下,你应该注意到这里发生了一些奇怪的事情:公式没有按我们所要求的方式计算。
理解计值环境
我们假定这个公式的含义是“所有销售额的总和”。但在透视表的每个单元格中,公式并未计算所有销售额的总和,它只计算具有特定颜色的产品销售额的总和。然而,我们从未指定计算必须在数据模型的子集上发生。换句话说,该公式没有被指定是否可以处理数据的子集。
为什么公式在不同的单元格中计算不同的值?答案的确很简单:是因为 DAX 在计值表达式时所处的上下文环境。你可以把一个公式的上下文环境看作是 DAX 计算公式时所在的单元格周围的区域。
因为产品颜色位于行上,所以数据透视表中的每一行都只能看到,在整个数据库中,该特定颜色的产品子集。这是公式的周围区域提供的上下文环境,即在公式计算之前应用于数据库的一组筛选器。当公式计算所有销售金额的总和时,它不会在整个数据库中计算它,因为它无法查看所有行。当 DAX 计算产品颜色值为白色的行所使用的公式时, 只有白色产品是可见的,因此, 它只考虑与白色产品相关的销售。所以对于所有销售额总和这个度量值,当计算透视表中只显示白色产品的行时,就变成了所有白色产品销售额的总和。
另一个示例,图中红色单元格计值的影响因素:
任何 DAX 公式都会指定计算,但 DAX 的计算发生在计值上下文中,而上下文定义了被计算出的最终结果。公式始终相同,但结果不同,因为 DAX 根据不同的数据子集执行计算。
简单起见, 下面的示例使用了数据透视表。你也可以使用查询或在 Power BI 报表环境中定义筛选上下文,你将在后续文章中详细了解。现在,我们只使用最简单的案例,只考虑数据透视表,以便对概念有一个简化和直观的理解。
案例扩展
继续最初的案例,现在让我们把年份放在列上, 使数据透视表内容更加丰富。
我们已经明确了计算规则:即使公式总是相同,每个单元格都可以有不同的值,因为对透视表行和列的选择都影响了上下文。事实上,2008 年白色产品的销售额与 2007 年白色产品的销售额有所不同。而且,由于可以在行和列中放置多个字段,所以其实是行上的字段集和列上的字段集共同定义了筛选上下文。下图更加明显地说明了这一点。
每个单元格有不同的值,因为行标签上有两个字段,颜色和品牌名称。行和列上的整个字段集定义了上下文。例如,上图中突出显示的单元格的上下文对应了黑色、Contoso 品牌和日历年 2007。
让我们看看这个案例现在的全貌。我们在切片器上添加了产品类别, 并在筛选条件下的月份名称中选择了 12 月。
小结
有一点很清楚:每个单元格中计算的值都有一个由行、列、切片器和筛选器定义的筛选上下文。所有这些筛选条件都共同定义了上下文环境, DAX 在公式计值之前将上下文应用到模型中。此外,重要的是要知道不仅是值,而且在字段方面,不是所有的单元格都有相同的筛选器集合。例如,列上的总计只包含类别、月份和年份的筛选器,但不包含颜色和品牌的筛选器。颜色和品牌的字段在行上,它们不筛选总计。这同样适用于数据透视表中的颜色分类汇总:对于这些单元格,制造商字段没有筛选器,来自行的唯一有效筛选器是颜色。
我们将这种上下文称为筛选上下文, 顾名思义, 它是筛选表的上下文。任何你编写的公式根据(DAX 用于执行其计算的)筛选上下文的不同,都将具有不同的值。这种行为虽然非常直观, 但仍需要很好的理解。
现在你已经了解了什么是筛选上下文,所以下面的 DAX 表达式应该被理解为“在当前筛选上下文中可见的所有销售额之和”:
[Sales Amount] := SUMX ( Sales, Sales[Quantity] * Sales[UnitPrice] )
稍后你将学习如何读取、修改和清除筛选上下文。到目前为止,对以下事实有充分的了解就足够了:对于透视表的任何单元格或报表/查询中的任何值,始终存在筛选上下文。想要理解 DAX 如何计算一个公式,你总是需要考虑筛选上下文。
创建筛选上下文的方式
从前面的例子你已经了解到创建筛选上下文最常用的一种方式,通过透视表、可视化图表、切片器和筛选器创建筛选上下文。
计算列中的筛选上下文环境
上面介绍的都是报表页环境中的筛选上下文,其实,还有一处我们经常使用但是容易忽略的环境,就是计算列中的筛选上下文。
样例文件说明
DAX 圣经第一版案例使用官方的 Contoso 数据库,你可以从这里直接下载。书中的原理部分虽然没有提供示例文件,你可以使用下载的文件进行练习。
原文小结有句话;“颜色和品牌的字段在行上,它们不筛选总计。”请问老师这句话怎么理解,grand total中的筛选上下文不是包含这两个字段吗?
我来吐槽一下上下文,先把这个最初翻译这个字的人拉过来枪毙5分钟,不能更简洁明了地翻译一下吗?非要给大家的学习设置障碍,你说一篇文章中的某个词、某句话要考虑上下文去理解它的意思这样大家都好理解,到了power bi哪来的上下文???
翻译成条件不好吗?一切计算的结果都是根据条件来的,这样多简洁明了。
老实说直接看拓展表比看这个解释要清晰简单很多,本质就是沿着关系自动拓展成了宽表,在这个宽表的基础上对列进行了筛选。
因为产品颜色位于行上,所以数据透视表中的每一行都只能看到,在整个数据库中,该特定颜色的产品子集。这是公式的周围区域提供的上下文环境,即在公式计算之前应用于数据库的一组筛选器。当公式计算所有销售金额的总和时,它不会在整个数据库中计算它,因为它无法查看所有行。当 DAX 计算产品颜色值为白色的行所使用的公式时, 只有白色产品是可见的,因此, 它只考虑与白色产品相关的销售。所以对于所有销售额总和这个度量值,当计算透视表中只显示白色产品的行时,就变成了所有白色产品销售额的总和。
看了半天,感觉使用“集合”和“指针”来去解释会更加容易懂一点
请问老师,我付费了但是怎么显示下载错误?谢谢
老师,能帮我看下下面这个结果的原因吗,万分感谢!!
我的疑问:矩阵的行标签不应该只是筛选单列的么,根据我的观察,下图矩阵中的行标签把相同表的索引列也设置了一个筛选器。
你好,老师,请问”计算列中没有任何外部筛选上下文,公式总是在整个数据库环境下计值“的意思是:因为计算列在数据表刷新时计算,而内存中表刷新时是不会有任何筛选器的,因此计算列的上下文是整个数据库环境。这样理解对吗?
老师,读完后,我的认知是:
1. DAX 表达式是始终在计值上下文中计算
2. 筛选上下文决定了,所引用列用来计算的行,以此限定了用于计算的数据库子集。然后执行计算
3. DAX 表达式必须有筛选上下文,当筛选上下文是空,计算集合是整个数据库全集,当不为空,根据筛选条件决定模型数据库子集
4. 我所直观看到的,切片器,数据透析表和表以及其他视觉对象的行列轴,视觉对象和页面筛选器 和calculate/calculatetable 内的filter argument 都是筛选上下文,它们以and 形式共同定义了引用列的哪些行需要计算,也就是用于计算的数据库子集。
在计算列中,calculate是可以的改变上下文?我实现了下,结果是,用calculate(sum(),filter),筛选后,是计算了子集,但是确是,每个子集中,每行对应得值,不知所以然
老师,图例也可以作为切片器吗?例如能被selectedvalue 取值?谢谢
请问高老师,您说“计算列中没有任何外部筛选上下文,公式总是在整个数据库环境下计值”,但是为什么又在“提示”当中说“因为随着你学习了 CALCULATE 和上下文转换的知识后,计算列的筛选上下文可以变的非常复杂”?我想问的是,在计算列中到底有没有筛选上下文环境呢,如果有的话该怎么创建呢?
我的会员是过期了吗?每次都要看充值才能看隐藏内容
相应的数据有吗,实操一遍加深理解
“计算列中的没有任何外部筛选上下文,公式总是在整个数据库环境下计值”
这句话不太通顺,建议改一下,计算列中没有任何外部筛选上下文,公式总是在整个数据库环境下计值