使用-DAX-的-UDF-的真实世界示例
使用 DAX 的 UDF 的真实世界示例
原文:
towardsdatascience.com/a-real-world-example-of-using-udf-in-dax/
简介
用户定义函数的功能是在 2025 年 9 月的发布中作为第一个预览版本引入的。
此功能使我们能够将业务逻辑封装在函数中,这些函数可以像任何其他标准函数一样被调用。
在本文中,我将通过一个真实世界的示例演示如何使用此功能:基于通货膨胀率计算预测。
你将看到如何创建一个简单的函数并处理更复杂的情况。
场景
让我们想象一家公司想要通过通货膨胀模拟来预测其收入。
他们想模拟不同的通货膨胀率如何影响他们的月收入。
为了简单起见,我们忽略季节性,并使用最后已知的月销售额来计算剩余年份的未来收入。
用户必须能够设置一个通货膨胀率并查看数字如何变化。
准备数据模型
现在,这取决于我是从一个新的 Power BI 文件开始并加载数据,还是将此功能添加到现有的文件中。
第一件事是激活预览功能:

图 1 – 启用用户定义函数的预览功能(图由作者提供)
你可能需要在启用它之后重新启动 Power BI Desktop。
对于现有的 Power BI 文件,我们需要设置正确的兼容性级别以创建用户定义的函数(UDFs)。
你可以创建一个虚拟函数,这将自动升级兼容性级别,或者使用 Tabular Editor 将其设置为至少 1702:

图 2 – 使用 Tabular Editor 升级数据库的兼容性级别(图由作者提供)
你可以在标记的字段中输入 1702 并保存。
我将在本文的后面部分演示如何创建一个简单的 UDF。
请访问微软文档了解有关在 Power BI Desktop 中创建新 UDF 的更多信息。您可以在本文末尾的参考部分找到链接。
添加比率选择
由于用户必须能够选择通货膨胀率,我在数据模型中添加了一个参数:

图 3 – 为数值范围向数据模型添加参数(图由作者提供)
在点击“数值范围”后,我填写了表格:

图 4 – 设置百分比范围的参数(图由作者提供)
由于我想控制百分比,我将范围设置为 -0.02 到 0.05,这相当于 -2% 到 5%。
几秒钟后,新的筛选器自动添加到报告页面上。
但它只显示小数数字。
我必须更改数字格式以查看百分比:

图 5 – 将参数的列格式化为百分比(图由作者提供)
现在切片器显示所需的数字:

图 6 – 以百分比显示数字的切片器(图由作者提供)
现在它已经准备好使用。
编写第一个函数
首先,让我们创建一个 UDF 来返回选定的比率。
我更喜欢在 Tabular Editor 中编写,因为它的 DAX 编辑器比 Power BI Desktop 快得多。
但你也可以在 Power BI Desktop 的 DAX 查询视图中创建它。
在 Tabular Editor 中,我转到函数节点,右键单击它,并选择“新建用户定义函数”:

图 7 – 在 Tabular Editor 中创建新的 UDF(图由作者提供)
现在,我可以设置一个名称。
对于这个第一个,我设置为“ReturnRate”。
这是函数的代码:
(
Rate : DECIMAL VAL
)
=>
Rate
在括号内,我定义了输入参数。
在 => 之后,我可以输入函数的 DAX 代码。
在这种情况下,我返回输入参数。
现在,我创建一个度量来使用这个函数:
Get Inflation rate = ReturnRate([Inflation rate Value])
当我创建用于选择通货膨胀率的参数时,创建了度量 [Inflation rate Value]。
当我添加一张卡片并将新的度量值分配给它时,我将看到来自切片器的选定值:

图 8 – 两个示例显示调用函数的度量返回选定的通货膨胀率(图由作者提供)
好的,这是一个基础函数,但只是为了说明它是如何工作的。
编写真正的函数
您可能已经注意到了参数定义中的关键字 VAL。
如您在以下两篇文章中更详细地阅读的那样,我们有两种传递参数的模式:
-
VAL: 直接传递参数内容。
-
EXPR: 将参数作为表达式传递,这可以在函数内部像通常的度量一样使用。
在以下函数中,我使用了这两个变量。
这里是函数 MonthlyInflation 的完整代码:
(
Rate : DECIMAL VAL
,InputVal : EXPR
)
=>
VAR CurrentMonth = MAX( 'Date'[MonthKey] )
VAR LastMonthWithData = CALCULATE(
LASTNONBLANK( 'Date'[MonthKey]
, InputVal
)
, ALLEXCEPT( 'Date', 'Date'[Year] )
)
VAR LastValueWithData = CALCULATE(InputVal
,ALLEXCEPT('Date', 'Date'[Year])
,'Date'[MonthKey] = LastMonthWithData
)
VAR MonthDiff = CurrentMonth - LastMonthWithData
VAR Result = IF(MonthDiff<=0
,InputVal
,(1 + ( Rate * MonthDiff ) ) * LastValueWithData
)
RETURN
Result
函数的第一个参数与之前相同。
第二个参数将是输入度量的表达式。
在函数内部,我可以使用参数名称来更改筛选上下文和其他内容。当我需要在函数内部以这种方式工作时,我必须将参数设置为 EXPR。
函数执行以下步骤:
-
我获取最高的 MonthKey 并将其存储在变量
CurrentMonth中内容是当前筛选上下文中的月份,以数值形式 YYYYMM 表示。
-
我使用输入参数(度量)中的值获取当前年份的最新月份并将其存储到变量
LastMonthWithData中 -
我从最新的有数据的月份中减去当前月份以获取差异。这将作为计算通货膨胀率的因子。结果存储在变量
MonthDiff中 -
如果 MonthDiff 小于或等于 0,则筛选上下文(月份)包含来自输入变量的值
-
如果不是,过滤上下文(月份)在未来,我们可以计算结果。
我在这里做的是将所选的通货膨胀率乘以自上个月有数据以来的月份数(LastMonthWithData)。
现在,我可以创建一个度量值,根据所选的通货膨胀率动态地按月计算预测值:
Online Sales With Inflation =
MonthlyInflation([Inflation rate Value], [Sum Online Sales])
这是 3%通货膨胀率的结果:

图 9 – 使用新的 UDF 根据所选通货膨胀率计算每月收入的结果(图由作者绘制)。
蓝色标记的月份包含实际数据,红色标记的月份是根据所选通货膨胀率计算的。
美妙的是,我可以将任何 DAX 表达式传递给我想要的度量值。
例如,我可以将在线销售与零售销售相加:

图 10 – 调用函数时添加在线和零售销售以计算总销售额的结果。
这个度量值的计算如下:
Total Sales With Inflation =
MonthlyInflation([Inflation rate Value], [Sum Online Sales] + [Sum Retail Sales])
嗯,这非常简单。
我知道计算非常简单,但我使用这个例子来展示可以使用 UDF 做什么。
重点是?
那么,UDF 的要点是什么?
这里展示的大部分内容也可以使用计算组完成。
嗯,这是真的。
但使用 UDF 比使用计算项要简单得多。
此外,我们可以编写模型无关的 UDF 并在多个模型中重用它们。
查看如何使用 DAX Lib 扩展 Power BI:Extend Power BI with DAX Lib。
这是一个不断增长的包含逻辑的模型无关 UDF 集合,这些逻辑可以在任何数据模型中使用。
UDF 和计算项之间的其他不同点包括:
-
UDF 不能分组,但计算项可以在计算组中分组。
-
计算项没有参数。
-
UDF 可以像任何其他 DAX 函数一样直接调用。
尝试一下,了解更多关于 UDF 的可能性。
结论
我相信了解如何使用 UDF 将变得越来越重要,因为随着时间的推移,它们的潜力将变得更加明显。
由于我们处于这个功能的早期引入阶段,我们需要保持关注,看看微软接下来将如何改进它。
在这个功能中存在一些限制。您可以在这里找到它们:DAX 用户定义函数的考虑和限制。
改进的空间足够大。
让我们看看接下来会发生什么。
参考
这里,有关用户定义函数的微软文档:使用 DAX 用户定义函数(预览)- Power BI | 微软学习。
这是解释该功能的 SQL BI 文章,详细介绍了该功能:介绍 DAX 中的用户定义函数 – SQLBI。
一系列免费使用的模型无关 UDF:通过 DAX Lib 扩展 Power BI。
如同我之前的文章一样,我使用了 Contoso 样本数据集。您可以从微软这里免费下载 ContosoRetailDW 数据集。
Contoso 数据可以在 MIT 许可证下自由使用,如在此文档中所述。我将数据集更改以将数据转移到当代日期。

浙公网安备 33010602011771号