DAX 公式中的上下文
您可以通过上下文执行动态分析,并且可以在动态分析中更改公式的结果以便反映当前行或单元选择以及任何相关数据。 了解上下文并有效使用上下文对构建高性能的动态分析和解决公式中的问题至关重要。
本节将定义不同类型的上下文:“行上下文”、“查询上下文”和“筛选上下文”。 本节解释如何针对计算列和数据透视表中的公式计算上下文。
本节的最后一部分提供了一些指向详细示例的链接,这些示例阐释了公式的结果如何随上下文的不同而变化。
上下文简介
PowerPivot 中的公式可受到在数据透视表中应用的筛选器、表之间的关系以及公式中使用的筛选器的影响。 可以通过“上下文”执行“动态分析”。了解上下文对于构建公式和解决公式问题很重要。
有许多类型的上下文:“行上下文”、“查询上下文”和“筛选上下文”。
“行上下文”可被视为“当前行”。如果创建了计算列,则行上下文由每个单独行中的值以及与当前行相关的列中的值组成。 还有一些函数(EARLIER 和 EARLIEST)可从当前行获取值,然后在对整个表执行操作时使用该值。
“查询上下文”是指为数据透视表中的每个单元隐式创建的数据子集,具体取决于行和列标题。
“筛选上下文”是根据筛选约束(已应用于行或由公式中的筛选表达式定义)而允许在每列中存在的值集。
下面的主题更加详细地介绍了不同类型的上下文:DAX 公式中的上下文。
返回页首
行上下文
如果您在计算列中创建某一公式,则该公式的“行上下文”将包括来自当前行中所有列的值。 如果该表与其他表相关,则上下文还包括来自该其他表中与当前行相关的所有值。
例如,假设创建将同一表中的两列相加的计算列 =[Freight] + [Tax]。 此公式的行为类似于 Excel 表中自动引用同一行中的值的公式。 请注意,表不同于范围:不能通过使用范围表示法引用来自当前行之前的行的值,并且不能引用表或单元中的任意单个值。 您必须始终使用表和列。
行上下文自动遵循表之间的关系,以便确定相关表中哪些行与当前行相关联。
例如,下面的公式使用 RELATED 函数根据订单的发货目的地从相关表提取税金值。 通过使用当前表中的区域值,在相关表中查找该区域,然后从相关表中获取该区域的税率,从而确定税金值。
= [Freight] + RELATED('Region'[TaxRate])
此公式只是从 Region 表中获取当前区域的税率。 您不需要知道或指定连接这些表的键。
多行上下文
此外,DAX 还包括对表执行迭代计算的函数。 这些函数可以具有多个当前行和当前列上下文。 就编程而言,您可以创建对内部和外部循环进行递归操作的公式。
例如,假设您的工作簿包含一个 Products 表和一个 Sales 表。 您可能想要遍历整个 sales 表,该表中全都是涉及多个产品的交易,并且您还要找到在任何一个交易中为每个产品订购的最大数量。
在 Excel 中,这个计算要求一系列中间汇总值,并且一旦数据发生更改,还不得不重新生成这些汇总值。 如果您是 Excel 的超级用户,则可能能够生成将执行此工作的数组公式。 或者,在关系数据库中,您可以编写嵌套 select 语句。
但使用 DAX,您可以生成返回正确值的单个公式,并且只要您向表中添加数据,结果就自动更新。
=MAXX(FILTER(Sales,[ProdKey]=EARLIER([ProdKey])),Sales[OrderQty])
有关此公式的详细演练,请参阅EARLIER 函数。
总之,该 EARLIER 函数存储来自当前运算之前的运算中的行上下文。 在任何时候,该函数都在内存中存储两组上下文:一组上下文表示公式的内部循环的当前行,另一组上下文表示公式的外部循环的当前行。 DAX 自动在两个循环之间馈送值,以便您可以创建复杂的聚合。
查询上下文
“查询上下文”是指为公式隐式检索的数据子集。 将度量值字段或其他值字段放入数据透视表中的某个单元后,PowerPivot 引擎将检查行和列标题、切片器和报表筛选器以便确定上下文。 然后,PowerPivot 引擎会进行必要的计算,以填充透视数据表中的每个单元。 检索的数据集是各单元的查询上下文。
因为根据您放置公式的位置上下文可能会更改,所以,根据您是将数据透视表中的公式与许多分组和筛选器一起使用,还是在没有筛选器且具有最少上下文的计算列中使用公式,公式的结果也会更改。
例如,假设您创建下面的简单公式,用来计算 Sales 表的 Profit 列中的各值之和:=SUM('Sales'[Profit])。 如果您在 Sales 表内的计算列中使用该公式,则该公式的结果对于整个表将是相同的,因为公式的查询上下文始终是 Sales 表的整个数据集。 您的结果会包含所有地区、所有产品、所有年份等的利润。
但是,通常您不想数百次看到相同的结果,而是希望获取特定年份、特定国家/地区、特定产品或这些项的某些组合的利润,然后获取总计。
在数据透视表中,通过添加或删除列和行标题以及添加或删除切片器,可以轻松地更改上下文。 您可以在度量值中创建如上公式,然后将其放置于数据透视表中。 只要您将列或行标题添加到数据透视表中,就可以更改在其中计算度量值的查询上下文。 切片和筛选运算也会影响上下文。 因此,对于每个单元,在不同的“查询上下文”中计算在数据透视表中使用的相同公式。
筛选上下文
通过在公式中使用参数,为列或表中允许存在的值集指定筛选约束时,将添加“筛选上下文”。 基于其他上下文(如行上下文或查询上下文)应用筛选上下文。
例如,某个数据透视表基于行和列标题计算每个单元的值,如针对查询上下文的前一节中所述。 但是,在添加到数据透视表的度量值列或计算列中,可以指定筛选表达式来控制公式使用的值。 您还可以有选择地清除特定列上的筛选器。
有关如何在公式内创建筛选器的详细信息,请参阅FILTER 函数。
有关如何清除筛选器以便创建总计的示例,请参阅 ALL 函数。
有关如何在公式内有选择地清除和应用筛选器的示例,请参阅 ALLEXCEPT 函数。
因此,必须检查在数据透视表中使用的度量值或公式的定义,以便您在解释公式的结果时能了解筛选上下文。
确定公式中的上下文
在您创建公式时,PowerPivot for Excel 首先检查常规语法,然后根据当前上下文中的可能列和表检查所提供的列和表的名称。 如果 PowerPivot 找不到公式指定的列和表,则系统会显示错误消息。
如前所述,通过使用工作簿中的可用表、表之间的所有关系和所应用的所有筛选器来确定上下文。
例如,如果您刚刚将一些数据导入到新表中,但尚未应用任何筛选器,则该表中的完整列集将成为当前上下文的一部分。 如果有多个表通过关系相互链接,并且您所处理的数据透视表已通过添加列标题和使用切片器进行了筛选,则上下文将包括相关表和用于数据的任何筛选器。
上下文很有用的概念,但也可能导致很难排除公式问题。 我们建议您从简单的公式和关系入手来了解上下文的工作方式,然后开始在数据透视表中试验简单公式。 下一节还提供了一些示例,说明公式如何使用不同类型的上下文来动态返回结果。
公式中上下文的示例
RELATED 函数可展开当前行的上下文以包括相关列中的值。 这允许您执行查找。 该主题中的示例阐释筛选和行上下文的交互情况。
通过 FILTER 函数可以指定要包括在当前上下文中的行。 该主题中的示例还演示如何在执行聚合的其他函数内嵌入筛选器。
ALL 函数可在公式中设置上下文。 使用此函数可以覆盖因查询上下文而应用的筛选器。
通过 ALLEXCEPT 函数可以删除您所指定的筛选器之外的所有筛选器。 以上两个主题包括的示例将引导您构建公式和了解复杂的上下文。
通过 EARLIER 和 EARLIEST 函数,您可以执行计算以便循环遍历表,并引用内部循环中的值。 如果您熟悉递归的概念以及内部循环和外部循环,将领会到 EARLIER 和 EARLIEST 函数所提供的强大功能。 如果这些概念对您来说是全新的,则应仔细按照示例中的步骤执行,以便了解如何在计算中使用内部上下文和外部上下文。
引用完整性
本节讨论与 PowerPivot 表中由关系关联的缺失值相关的一些高级概念。 如果您的工作簿中包含多个表和复杂公式,并且您希望在了解结果方面获得帮助,本节内容可能非常有用。
如果不熟悉关系数据概念,建议您先阅读介绍性主题关系概述。
引用完整性和 PowerPivot 关系
PowerPivot 不要求为了定义有效的关系而在两个表之间强制执行引用完整性;而是在每个一对多关系的“一”端创建一个空行,用于处理相关表中所有非匹配行。 它有效地起到了 SQL 外部联接的作用。
在数据透视表中,如果您按关系的“一”端对数据分组,则关系“多”端上的所有非匹配数据都分为一组,将包含在总计中且行标题为空白。 空白标题大体相当于“未知成员”。
了解未知成员
如果您使用过多维数据库系统(如 SQL Server Analysis Services),您可能已经熟悉了未知成员的概念。 如果您不了解该术语,以下示例将解释什么是未知成员以及它如何影响计算。
假设您要创建一个计算,用于计算每个商店的月销售额总和,但 Sales 表中的一列缺少商店名称值。 假定 Store 和 Sales 表是通过商店名称连接的,您希望公式如何操作? 数据透视表如何分组或显示与现有商店无关的销售数字?
此问题在数据仓库中很常见,在这种情况下大型事实数据表必须在逻辑上与维度表相关,维度表包含商店、区域和其他用于分类和计算事实的属性的相关信息。 为了解决该问题,会将与现有实体无关的新事实临时分配给未知成员。 这就是无关事实之所以将在空白标题下出现的原因。
处理空白值与处理空白行
空白值与为了容纳未知成员而添加的空白行不同。 空白值是一种特殊值,用于表示 Null、空字符串和其他缺失值。 有关空白值以及其他 DAX 数据类型的详细信息,请参阅PowerPivot 工作簿中支持的数据类型。