Table of Contents

代码操作 DI005 (改进) 将表筛选器改写为标量谓词

描述

在可能的情况下,将 CALCULATE 的筛选参数改写为标量谓词,而不是使用 FILTER 函数。

示例 1

更改前:

CALCULATE([Total Sales], FILTER(Products, Products[Color] = "Red"))

更改为:

CALCULATE([Total Sales], KEEPFILTERS(Products[Color] = "Red"))

示例 2

更改前:

CALCULATE([Total Sales], FILTER(ALL(Products), Products[Color] = "Red"))

更改为:

CALCULATE([Total Sales], ALL(Products), Products[Color] = "Red")

示例 3

更改前:

CALCULATE(
    [Total Sales],
    FILTER(
        ALL(Products), 
        Products[Color] = "Red" 
            && Products[Class] = "High-end"
    )
)

更改为:

CALCULATE(
    [Total Sales], 
    ALL(Products),
    Products[Color] = "Red", 
    Products[Class] = "High-end"
)

Tabular Editor 为什么会提出这种建议?

CALCULATE 的筛选参数中使用 FILTER 对表进行筛选,效率不如直接对该表的一列或多列进行筛选。 将筛选器重写为标量谓词后,你的代码会更高效,占用更少的内存和 CPU 资源。

例如,像 FILTER(Sales, < condition >) 这样的表达式会遍历 Sales 表中的所有行,并对每一行计算该条件。 相比之下,像 Sales[Quantity] > 0 这样的表达式只会遍历 Quantity 列,效率高得多,也不会把 Sales 表的所有列都添加到筛选语境中。

使用标量谓词还能让代码更简洁、更易读。

在底层实现中,标量谓词只是语法糖,本质上等价于同样使用 FILTER 函数的表表达式。 不过,FILTER 函数只会应用于单列,因此比筛选整张表更高效。

何时不会显示此建议

从 Tabular Editor 3.25.0 起,当 FILTER 表达式中发生表扩展时,不再建议执行此代码操作。 这是因为在这种情况下,将表筛选重写为标量谓词可能会改变筛选的语义,从而产生不同的结果。

表扩展场景

当 DAX 自动包含关系中“一”端的相关表时,就会发生表扩展。 例如,如果你筛选 Sales 表,DAX 会自动扩展该筛选,使其包含相关的维度表,如 ProductCustomer 等。

当你这样写:

CALCULATE(
    [Total Sales],
    FILTER(Sales, Sales[Quantity] > 10)
)

该筛选会作用于扩展后的 Sales 表,其中包含所有相关的维度表。 这意味着筛选语境不仅包含 Sales 表,还包含与 Sales 存在关系且位于关系“一”端的所有表。

为什么重写会改变结果

将表筛选转换为标量谓词,会改变受影响的表:

原始写法(有表扩展):

CALCULATE([Total Sales], FILTER(Sales, Sales[Quantity] > 10))

这会筛选_扩展后的_ Sales 表,从而影响 Sales 以及所有相关的维度表。

重写后(标量谓词):

CALCULATE([Total Sales], Sales[Quantity] > 10)

这只会筛选 Sales[Quantity] 列,因此不会触发对相关维度表的表扩展。

在大多数情况下,这种差异无关紧要,因为相关的维度表不会影响计算。 不过,在某些情况下,尤其是涉及关系或计算表格时,这两个表达式可能会得到不同的结果。 为确保结果正确,当检测到表扩展时,Tabular Editor 会避免建议进行这种改写。

延伸阅读