4.4 了解FILTER,ALL和上下文交互
了解FILTER,ALL和上下文交互
在前面的示例中,我们使用FILTER作为筛选表的便捷方法。FILTER是一项常见功能,可在需要进一步限制现有筛选上下文的筛选时使用。
想象一下,我们要创建一个计算红色产品数量的度量值。利用目前为止获得的知识,公式很简单:
NumOfRedProducts :=
VAR RedProducts =
FILTER (
'Product',
'Product'[Color] = "Red"
)
RETURN
COUNTROWS ( RedProducts )</pre>
我们可以在报表中使用此公式。例如,将产品品牌放在行上以生成如图4-14所示的报告。
图4-14 使用FILTER功能来计算红色产品的数量在继续进行本示例之前,请稍等片刻,仔细考虑DAX如何计算这些值。品牌是产品表的一列。在报表的每个单元格中,筛选上下文筛选一个给定的品牌。因此,每个单元格显示给定品牌产品的数量也为红色。原因是FILTER会在当前筛选上下文中可见的情况下对 Product 表进行迭代,该表仅包含具有该特定品牌的产品。似乎微不足道,但是最好重复几次,而不要忘记它。
如果我们在报告中添加切片器以筛选颜色,则这一点更加明显。在图4-15中,有两个完全相同的报告,都带有筛选颜色的切片器,其中每个切片器仅在其紧邻的右边筛选报告。左侧的报告筛选红色,数字与图4-14相同,而右侧的报告为空,因为切片器正在过滤Azure。
DAX在考虑切片器定义的外部上下文的情况下评估NumOfRedProducts有两个报告。在左侧,我们看到每个产品的NumOfRedProducts值,并且切片器将焦点放在Red上。在右侧,切片器将重点放在Azure上,并且报告为空。
在右侧的报告中,由FILTER迭代的 Product 表仅包含Azure产品,并且由于FILTER只能返回Red产品,因此没有要返回的产品。结果,NumOfRedProducts度量值始终评估为空白。
此示例的重要部分在于,在同一公式中,既有来自外部的筛选上下文——受切片器选择影响的报表中的单元格,也有公式中FILTER函数引入的行上下文。这两个上下文同时工作并修改结果。在FILTER进行的迭代过程中,DAX使用筛选上下文评估 Product 表,并使用行上下文逐行评估筛选条件。
我们想再次重复这个概念:FILTER不会更改筛选上下文。FILTER是一个迭代函数,它扫描表(已由筛选上下文筛选),并根据筛选条件返回该表的子集。在图4-14中,筛选上下文正在筛选品牌,在FILTER返回结果之后,它仍然仅筛选品牌。在图4-15中将切片器添加到颜色之后,筛选上下文同时包含品牌和颜色。因此,FILTER在左侧报告中返回了所有迭代的产品,而在右侧报告中未返回任何产品。在这两个报告中,FILTER均未更改筛选上下文。FILTER仅扫描表并返回筛选结果。
此时,可能需要定义另一个公式,该公式返回红色乘积的数量,而不管在切片器上进行的选择如何。换句话说,代码需要忽略在切片器上所做的选择,并且必须始终返回所有红色乘积的数量。
为此,可以使用ALL功能。ALL返回忽略筛选上下文的表的内容。我们可以使用以下表达式定义一个名为NumOfAllRedProducts的新度量值:
NumOfAllRedProducts :=
VAR AllRedProducts =
FILTER (
ALL ( 'Product' ),
'Product'[Color] = "Red"
)
RETURN
COUNTROWS ( AllRedProducts )
这次,FILTER不迭代产品。而是,迭代ALL(Product)。* ALL会忽略筛选上下文,并始终返回表的所有行,因此FILTER*会返回红色产品,即使先前已使用其他品牌或颜色筛选的产品也是如此。 尽管正确,但图4-16中所示的结果可能令人惊讶。
图4-16 NumOfAllRedProducts返回奇怪的结果同样,左侧的报告侧重于红色,右侧的报告侧重于天蓝色。这次在右侧的NumOfAllRedProducts下有一个值。 。
这里需要注意几个有趣的事情,我们想更详细地描述两者:
-
无论行上选择的品牌如何,结果始终为99。
-
左矩阵与右矩阵中的品牌不同。
首先,红色产品的总数为99,而不是任何给定品牌的红色产品的数量——如预期的那样,是所有产品,忽略了产品表上的筛选。它不仅忽略了颜色上的筛选,而且忽略了品牌上的筛选,这可能是不希望的效果。尽管如此,ALL既简单又强大,是一个全有或全无的函数。如果使用,ALL将忽略应用于作为其参数指定的表的所有筛选。运用到目前为止您已经掌握的知识,还不能选择仅忽略筛选的一部分。在该示例中,最好只忽略颜色上的筛选。只有在下一章介绍了CALCULATE之后,您才有更好的选择来实现对筛选的选择性忽略。
现在让我们描述第二点:两个报告上的品牌不同。由于切片器正在筛选一种颜色,因此将使用该颜色上的筛选来计算整个矩阵。左边的颜色是Red,而右边的颜色是Azure。这确定了两组不同的产品,进而确定了品牌。用于填充报告轴的品牌列表是在原始筛选上下文中计算的,该筛选上下文中包含颜色筛选。一旦计算了轴,DAX将计算该度量值,无论品牌和颜色如何,结果始终返回99。因此,左侧的报告显示了红色产品的品牌,而右侧的报告显示了天蓝色产品的品牌,尽管在这两个报告中,度量值均显示了所有红色产品的总数,而与品牌无关。
注意
报表的行为并不特定于DAX,而是特定于Power BI使用的SUMMARIZECOLUMNS函数。我们将在第13章“编写查询”中介绍SUMMARIZECOLUMNS。
我们现在不希望进一步探讨这种情况。当您学习CALCULATE时,该解决方案就会出现,它为处理筛选上下文提供了更多的功能(和复杂性)。到目前为止,我们已经使用该示例说明了由于上下文交互以及在同一表达式中筛选和行上下文的共存,您可能会从相对简单的公式中发现意外结果。