03.02 初识筛选上下文
计算列中没有任何外部筛选上下文,公式总是在整个数据库环境下计值# 初识筛选上下文任何DAX表达都是在上下文中计算的。上下文是公式计值的“环境”,也就是说,公式的结果始终受到环境的影响。总有两种上下文,它们分别是:筛选上下文和行上下文,统称为计值上下文。> 随着你对DAX了解的深入,会逐渐了解到“环境”和“上下文”都有着丰富的内涵,让我们先从最简单的概念开始,这篇文章让我们来认识筛选上下文
第一印象
思考这样一个非常简单的度量值:[Sales Amount]:=SUMX(Sales, Sales[Quantity] Sales[UnitPrice])你已经知道这个公式计算的内容:销售表中所有数量乘以价格的总和。你可以将这个度量值放在数据透视表中查看结果,如图所示。不含上下文的销售金额显示了总计值这个数字看起来平淡无奇。但是,如果你仔细想想,这个公式精确地计算了它应该计算的东西:所有销售额的总和,现在它只是一个数字。当我们使用一些列来分割它并开始深入研究时,这个数据透视表就开始变得有趣了。例如,你可以使用产品颜色列,将其放在行上,然后透视表马上就显示了一些有趣的业务信息。销售额的总和按颜色切片总计仍然存在,但现在它是一些更小的值的总和,每一个值,连同所有其他值,都有明确的意义。但是,如果你再仔细考虑一下,你应该注意到这里发生了一些奇怪的事情:公式没有按我们所要求的方式计算。## 理解计值环境 我们假定这个公式的含义是“所有销售额的总和”。但在透视表的每个单元格中,公式并未计算所有销售额的总和,它只计算具有特定颜色的产品销售额的总和。然而,我们从未指定计算必须在数据模型的子集上发生。换句话说,该公式没有被指定是否可以处理数据的子集。为什么公式在不同的单元格中计算不同的值?答案的确很简单:是因为DAX在计值表达式时所处的上下文环境。你可以把一个公式的上下文环境看作是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,在早期的文档中比较常见,大多数情况下我们不必做如此严格的区分
创建筛选上下文的方式
从前面的例子你已经了解到创建筛选上下文最常用的一种方式,通过透视表、可视化图表、切片器和筛选器创建筛选上下文。 值得注意的是,透视表和图表在初始状态下创建的是静态的筛选上下文,而报表层的交互操作可以新增或修改已有的上下文环境。比如
- 调整筛选器取值范围
- 图表之间的联动
- 层级钻取
- 页面钻取 除去上面这种最常见的方式,筛选上下文还有一种更重要的创建方式,就是通过CALCULATE和CALCULATETABLE在公式内部编程式的创建筛选上下文,使用这种方式,你可以调整报表层的筛选环境,调整公式的计值行为,以及借助上下文转换引入更多的筛选条件。毫不夸张的说,能否熟练运用CALCULATE决定了使用者的DAX水平,这部分内容我们将在CALCULATE函数一节中详细介绍。## 计算列中的筛选上下文环境 上面介绍的都是报表页环境中的筛选上下文,其实,还有一处我们经常使用但是容易忽略的环境,就是计算列中的筛选上下文。 当你需要创建计算列的时候,理解它所处的筛选上下文环境是非常有必要的,简单的说,计算列中没有任何外部筛选上下文,公式总是在整个数据库环境下计值,你可以参考本文使用的第一幅图。这个概念虽然基础,但是却非常重要,因为随着你学习了CALCULATE和上下文转换的知识后,计算列的筛选上下文可以变的非常复杂,明确公式的初始环境是理解公式的计值流的基础## DAX圣经第一版案例使用官方的Contoso数据库,你可以从这里直接下载。原理部分书中虽然没有提供单独的示例文件,你可以使用下载的文件进行练习。