DAX从入门到精通 5-2-2 使用复杂的过滤条件
当使用多个filter的时候,calculate用and的逻辑,把所有的筛选条件合并,然后形成新的筛选上下文。所以如果你要过滤所有生产商事Tailspin的black的产品,表示式可以这样写:
[Calculate Version] :=
CALCULATE (
SUM ( Sales[SalesAmount] ),
Product[Brand] = "Tailspin Toys",
Product[Color] = "Black"
)
因为calculate把两个条件用and合并,那么你可能会以为可以这样写:
[FILTER Version] :=
CALCULATE (
SUM ( Sales[SalesAmount]),
FILTER (
Product,
AND (
Product[Brand] = "Tailspin Toys",
Product[Color] = "Black"
)))
实际上,这两个表达式是不同的。我们已经学过了,这里再复习一下这节的重要概念。在使用布尔值的函数中,现有的筛选条件brand和color都被忽略了。而使用filter的表达式,已经存在的筛选上下文条件(优先于calculate的产生的筛选上下文)会先作用于这两个列。
因此,使用布尔值的版本所有行都会返回black Tailspin的销售额,而使用filter的版本,只有当行列的筛选条件也是black Tailspin的时候,才会显示计算值。
![](https://img.haomeiwen.com/i13528785/ea3296d150b91adb.png)
这样的区别是因为,filter的迭代条件,是会受到原始的外部筛选上下文影响的。
[Sales of Tailspin Toys] :=
CALCULATE (
SUM ( Sales[SalesAmount] ),
Product[Brand] = "Tailspin Toys",
)
等同于:
[Sales of Tailspin Toys] :=
CALCULATE (
SUM ( Sales[SalesAmount] ),
FILTER (
ALL ( Product[Brand] ),
Product[Brand] = "Tailspin Toys",
))
在后面一个公式中,通过使用all函数,我们就可以忽略了现有的作用于manufacturer的筛选条件。对于这些工作的规律,我们要时刻记得它们的重要性。虽然这里我们只是用作教学的目的,但是实际中,你会遇到很多类似的场景,有时候,你有会遇到奇怪的结果。为了明白函数是如何工作的,你必须要掌握上下文是如何工作的。
针对单个列,上述的等效公式写法可以正确运行。在我们的案例中,我们有两列,你可能会使用下列的方式来写等效的函数:
FilterAll Version :=
CALCULATE (
SUM ( Sales[SalesAmount] ),
FILTER (
ALL ( Product ),
AND (
Product[Brand] = "Tailspin Toys",
Product[Color] = "Black"
)))
这个函数也不能满足我们的需求,我们使用了all函数,忽略表的所有列的筛选条件(包含了我们需想排除筛选条件的列,以及表中的其他列)。为了看效果,我们把透视表设置的复杂一些。我们把category添加到行。
![](https://img.haomeiwen.com/i13528785/65a925c44e9ee337.png)
all函数忽略了整个product表。即便是calculate的值是空值的,新的度量值也是显示了值。这个原因是,calculate version忽略了color的筛选上下文,而filterall的函数忽略了整个表的列的筛选条件,因此也就忽略了category。
为了找到正确的写法,你必须要用列而不是表的方式来思考。我们不能把product直接用到filter参数中,也不能使用all(product)这样的写法。相反,我们需要一个product表,只移除了manufacturer上的过滤条件,而其他的过滤条件依旧保留。只有calculate函数才能做到这点,问题是,calculate要求一个表达式来返回一个值,而我们要返回的是一个表,我们需要将其作为一个filter函数的参数。幸运的是,calculate有个同伴calculatetable,它不是返回一个值,而是返回一个表。它可以用作是calculate中filter的参数,这个函数我们后面会介绍。