使用变量来改进你的 DAX 公式

作为数据建模器,编写和调试某些 DAX 计算可能具有挑战性。 复杂的计算要求通常涉及编写复合表达式或复杂表达式。 复合表达式可以涉及使用许多嵌套函数,并可能重复使用表达式逻辑。

在 DAX 公式中使用变量有助于编写更复杂的高效计算。 变量可以提高性能、可靠性、可读性并减少复杂性。

在本文中,我们将使用一个示例度量值来演示前三个权益,以衡量年销售额(YoY)的增长情况。 (同比销售额增长的公式是周期性销售额,减去去年同期的销售额,除以去年同期的销售额)。

让我们从以下度量值定义开始。

Sales YoY Growth % =
DIVIDE(
    ([Sales] - CALCULATE([Sales], PARALLELPERIOD('Date'[Date], -12, MONTH))),
    CALCULATE([Sales], PARALLELPERIOD('Date'[Date], -12, MONTH))
)

该度量值生成正确的结果,但现在让我们看看它是如何改进的。

提高性能

请注意,公式重复计算“去年同期”的表达式。 此公式效率低下,因为它要求 Power BI 评估同一表达式两次。 通过使用变量 VAR,可以更高效地实现度量值定义。

以下度量值定义表示改进。 它使用表达式将“去年同期”结果分配给名为 SalesPriorYear的变量。 然后,在 RETURN 表达式中使用变量两次。

Sales YoY Growth % =
VAR SalesPriorYear =
    CALCULATE([Sales], PARALLELPERIOD('Date'[Date], -12, MONTH))
RETURN
    DIVIDE(([Sales] - SalesPriorYear), SalesPriorYear)

该度量值将继续生成正确的结果,并在大约一半的查询时间内完成此操作。

提高可读性

在前面的度量值定义中,请注意变量名称的选择如何使 RETURN 表达式更易于理解。 表达式简短且易于理解。

简化调试

变量还可以帮助你调试公式。 若要测试分配给变量的表达式,请临时重写 RETURN 表达式以输出变量。

以下度量值定义仅返回 SalesPriorYear 变量。 请注意它注释掉预期 RETURN 表达式的方式。 通过此技术,可以在调试完成后轻松恢复它。

Sales YoY Growth % =
VAR SalesPriorYear =
    CALCULATE([Sales], PARALLELPERIOD('Date'[Date], -12, MONTH))
RETURN
    --DIVIDE(([Sales] - SalesPriorYear), SalesPriorYear)
    SalesPriorYear

降低复杂性

在早期版本的 DAX中,尚不支持变量。 引入新筛选器上下文的复杂表达式需要使用 EARLIEREARLIESTDAX 函数来引用外部筛选器上下文。 遗憾的是,数据建模器发现这些函数难以理解和使用。

变量始终在应用 RETURN 表达式的筛选器之外进行计算。 因此,在修改后的筛选器上下文中使用变量时,其结果与 EARLIEST 函数相同。 因此,可以避免使用 EARLIER 或 EARLIEST 函数。 这意味着现在可以编写不太复杂且更易于理解的公式。

请考虑以下添加到“子类别”表中的计算列定义。 它根据 子类别销售 列值计算每个产品子类别的排名。

Subcategory Sales Rank =
COUNTROWS(
    FILTER(
        Subcategory,
        EARLIER(Subcategory[Subcategory Sales]) < Subcategory[Subcategory Sales]
    )
) + 1

EARLIER 函数用于引用当前行上下文中的“销售子类别”列值。

可以使用变量而不是 EARLIER 函数来改进计算列定义。 CurrentSubcategorySales 变量将 子类别销售 列值 存储在当前行上下文中,RETURN 表达式在修改后的筛选器上下文中使用它。

Subcategory Sales Rank =
VAR CurrentSubcategorySales = Subcategory[Subcategory Sales]
RETURN
    COUNTROWS(
        FILTER(
            Subcategory,
            CurrentSubcategorySales < Subcategory[Subcategory Sales]
        )
    ) + 1