此内容由人工智能翻译,尚未经过人工编辑审核。图像和图表保持其原始语言。
要点总结
- 使用 DAX 在语义模型中创建计算。 要为 Report 定义这些计算,你需要引用语义模型中已有的表、列和关系。
- DAX(Data Analysis Expressions)是一种用于在 Power BI 和其他应用中分析数据 的查询编程语言。 你编写 DAX 表达式 在模型内部定义自定义计算或逻辑,而 Power BI 会使用 DAX 查询 从 Report 中查询该模型。
- DAX 是你的 Visual 与语义模型沟通、获取所需数据的方式。 尽管语法和结构相对简单,DAX 仍不容易精通。
本摘要由作者撰写,并非由 AI 生成。
编写计算,以便对数据进行分组和分析。
\n\n
在本系列中,我们分享如何在 Power BI 或 Analysis Services 中高效构建 语义模型(以前称为 Dataset)的技巧。 在 上一篇文章 中,我们介绍了如何验证模型关系——它们是表之间的链接,也是业务逻辑的基础。 创建并验证关系后,你的模型基础就已就绪,可以进入下一步了。
\n\n本文将介绍构建语义模型的下一步:通过编写 DAX 创建计算。 你将引用前几步已添加到模型中的表、列和关系,为 Report 定义这些计算。 这些计算用于 Report Visual 或 Excel 数据透视表,帮助你分析数据。
\n本文旨在概述基础知识——何时需要编写 DAX,以及如何在 Power BI Desktop、Tabular Editor 或 Microsoft Fabric 中完成这件事。
\n\n
注意\n\n
\n\n
\n
\n
\n构建满足你数据需求的语义模型有很多同样可行的方法。 本系列介绍其中一种做法,并分享我们经验中的技巧与最佳实践。 请参阅下方本系列已发布的其他文章: \n
|
什么是 DAX?
\n数据分析表达式(DAX)是一种函数式和查询型编程语言,用于在 Power BI 和其他应用中分析数据。 你编写 DAX 表达式,在模型内定义自定义计算或逻辑;而 Power BI 会使用 DAX 查询从你的 Report 中查询该模型。 DAX 是你的 Visual 与语义模型通信、检索所需数据的方式。 你编写的函数式 DAX 就像一组指令,告诉模型该使用哪些表和列,以及要对它们做什么。 编写 DAX 时,你会引用表、关系、列以及其他计算(度量值),然后使用 SUM 或 AVERAGE 或 FILTER 等函数来聚合或筛选数据。
\n\n
提示\n \n |
\n
前面的示例可以这样理解:
- \n
- 第一张图展示了一个度量值 [Selling Margin (Value)]。 它会对 ‘Invoices’ 表中每一行的 ‘Invoices’[Net Invoice Value] 减去 ‘Invoices’[Net Invoice Cost] 的结果使用 SUM 进行求和。 由于销售毛利只应针对发票单据计算(而非其他单据类型),CALCULATE 函数会使用相关的 ‘Invoice Document Type’[Invoice Type] 列对结果应用 FILTER 筛选,使其仅包含发票;该列位于一个维度表中,并与事实表 ‘Invoices’ 相关联。 度量值通常在 DAX 查询中使用,其结果会随当前激活的 FILTER 筛选条件而变化。 \n
- 第二张图展示了按月统计发票行的 DAX 查询。该查询在 DEFINE 中定义了度量值 [Invoice Lines](因此它只存在于该查询中),并在查询中(EVALUATE 之后)使用它来计算每月的行数。 开发人员可能会定期运行这样的查询,用于验证模型或底层数据。 查询也可以指在模型中定义的度量值。
DAX 贯穿整个 Power BI 解决方案。 下图对在 Power BI 的模型和 Report 中,你可能在不同位置编写 DAX 的情况做了一个基本概览。
DAX 贯穿整个 Power BI
- 语义模型:你会在模型中编写 DAX,用于定义可即时计算的度量值,或在模型刷新时计算的计算表格与计算列。 DAX 表达式也用于定义行级安全性 (RLS) 规则,也称为表格权限。 DAX 也用于更高级的模型对象,例如计算组项、动态格式字符串和明细行。
- 查询:DAX 查询是 Power BI 从模型检索数据、为 Report 中的 Visual 填充数据的方式。 你也可以在 Power BI Desktop 中自行编写查询,也可以使用 Tabular Editor、DAX Studio 等其他工具,或在带有 Semantic Link 的 Fabric 笔记本里编写查询。
- Report:你可以在连接到已发布语义模型的“轻量级”Report 中编写 DAX 度量值。 这通常只用于该 Report 特有的度量值,而不是计算(计算更适合放在模型中)。
- Visual:你可以在 Power BI Visual 中编写一种特殊类型的 DAX,称为视觉计算。 视觉计算不属于模型,只使用该 Visual 中的数据来生成计算结果。
“DAX 很简单,但并不容易”
DAX 在语法和结构上很简单,但众所周知,DAX 并不容易学习。 乍一看,DAX 很像 Excel 公式语言那样简洁,但这很容易产生误解:为了覆盖比 Excel 更丰富的场景,它实际上要复杂得多。 由于 DAX 依赖于 Data model,而不是工作表上的单元格位置,作者必须“用数据模型来思考”,这对刚接触数据建模的新手来说尤其有挑战性。 下面这些是有经验的开发人员习以为常的概念,但新开发人员必须在实践中逐步掌握:
- 一个模型包含多个表格,这些表格通过关系连接。
- 筛选会沿着关系按方向从一个表传播到另一个表。
- 在一条关系链中,“一”端的属性可以对“多”端的值进行分组。
DAX 之所以难学,还有一个原因是:它的运行方式与其他编程语言不同。 DAX 中有些约定是 DAX 独有的;它有自己独特的“思考”方式。 这意味着,一些有其他语言经验的开发人员可能会套用在 DAX 中不适用的约定或实践——更糟的是,它们看似能跑通,但结果并不理想。
- Python 示例:你不应该像在 Python 中使用 for loop 或 while loop 那样,在 DAX 中使用“循环”。
- SQL 示例:你不应该像在 SQL 中用 CASE/WHEN 那样,在 DAX 里用 IF/THEN 来做条件聚合。
下面再举几个例子:这些特定的约定或规则,在你刚开始写 DAX 时往往很难理解。
- 你可以通过 CALCULATE 或 CALCULATETABLE 等函数来修改计算。 使用这些函数时,你会提供两类不同的参数:筛选器(用于筛选结果)和 CALCULATE 修饰符(用于改变这些函数的行为)。
- CALCULATE 修饰符可以让你更精细地调整计算结果,但前提是你理解正在修改的中间结果。
- 筛选器其实是表——这个概念对新用户来说很难理解。
- DAX 会在决定结果的语境中进行求值。 编写 DAX 时需要了解两种主要语境:筛选语境和行语境。
- 筛选语境会对数据进行筛选。 筛选语境的示例包括:
- 当 Report 中的筛选器或切片器处于活动状态,或用户通过交叉筛选、下钻或钻透等方式应用了筛选,并且在该 Report 的某个 Visual 中对 DAX 表达式求值时。
- 当在 Visual 中针对某个特定数据点(例如某个类别或类别组合)对 DAX 表达式求值时。
- 当某个计算将筛选语境作为 CALCULATE 的参数传入时(例如 ‘Date'[Month] = “January” )。 该筛选语境会覆盖引用列上的其他筛选,除非使用 KEEPFILTERS 这个 CALCULATE 修饰符。
- 行语境会迭代表格。 行语境的示例包括:
- 当你在计算列中对 DAX 表达式求值时。 例如,如果你在计算列中对 ‘Invoices’ 表里的 ‘Invoices’[Sales] – ‘Invoices’[Cost] 求值,它会对 ‘Invoices’ 表使用行语境,从而为每一行计算出一个结果。
- 当你在迭代器函数中对 DAX 表达式求值时。 例如,如果你在某个 DAX 度量值中对 SUMX( ‘Invoices’, ‘Invoices’[Sales] – ‘Invoices’[Cost] ) 求值,它同样会对 ‘Invoices’ 表使用行语境。
- 语境转换这一概念:即通过使用 CALCULATE 函数,将行语境转换为等价的筛选语境。 很多人在刚开始编写 DAX 时,语境转换往往是性能问题的来源之一。
提示你可以在 Tabular Editor 中使用 DAX调试器查看 DAX 表达式的中间求值结果。 这对学习和排查 DAX 代码问题都很有帮助。 我们会在后续文章中讲解该调试器。 |
提示当你在 Tabular Editor 3 中编写 DAX 时,它会为你指出这些特殊约定。 例如,工具提示会告诉你 calculate 的参数、当前激活的语境,以及语境转换发生的时机。 这样你就可以专注于编写 DAX。 你可以按下快捷键 Ctrl + Shift + Spacebar,即可切换此工具提示,使其在光标所在位置弹出。
|
上面的概念听起来可能有点吓人,但别怕 DAX;它非常优雅且功能强大。 尽管很多 LinkedIn 网红会告诉你,你 完全可以不必精通某样东西,也能从中获益并获得价值。 例如,在少数情况下,你的语义模型甚至可能不需要 DAX。
我的模型需要编写 DAX 吗?
你可以创建一个完全不含 DAX 的模型,并使用该 Data model 制作 Report。 例如,如果你只会用 Report 展示带描述性属性的数据或未汇总的数据,就没有必要编写任何 DAX。 例如,用于产品目录的报表,或用于按行项目浏览订单单据的报表;这类报表展示的是未汇总在一起的原始交易记录。 不过,这类 Report 并不常见,因为 Power BI Report(以及它使用的 VertiPaq 引擎)的优势在于高效汇总并通过 Visual 可视化规模大、结构复杂的数据。
你也可以使用 隐式度量值,在不编写 DAX 的情况下分析数据。
隐式度量值
隐式度量值指的是:在 Power BI 中对数值列进行聚合而无需编写任何 DAX。 相反,你只需添加该列,系统就会应用默认的汇总方式,并按某个维度对数据进行分组。 你可以从一组默认选项中更改这种汇总方式。 之所以称为 隐式度量值,是因为在后台,Power BI 会在 Visual 生成的 DAX 查询中即时为你创建该度量值。
下图展示了一个隐式度量值示例:从 Quantity 列生成 SUM of Quantity ,并在 Visual 中按文本列 Category 分组。
对于业务用户或刚接触 Power BI 的人来说,隐式度量值可能是个不错的选择,尤其是当他们没有任何编写代码的经验时。 此外,即使是有经验的开发者,在做快速的 ad hoc 即席分析时也可能会用到隐式度量值(例如在探索数据或分析一个短期模型时)。
如果你确实打算使用隐式度量值,请考虑以下几点。
- 将“Default Summarization”属性设置为合适的聚合方式。 对于不应聚合的列,例如 ‘Orders’[Order Number],将其设置为 None 。
- 使用显示文件夹将可聚合的数值列与不可聚合的列分开整理。
- 为列设置描述,以明确应使用哪些聚合方式。
- 如果隐式度量值无法带来明确价值,就不要使用它。 尤其要避免对计算列使用隐式度量值,例如把它当作绕开棘手 DAX 场景的手段。
隐式度量值可能会带来一些问题和注意事项,需要提前了解。
- 可选项仅限于最常用的几种聚合。
- 由于你无法控制 DAX,因此也就无法修改计算逻辑。
- 这些计算不会出现在字段列表中,这会让开发者更难理解模型的使用方式,也更难在不同报表之间保持一致。
- 添加计算组会在模型中抑制隐式度量值,这意味着用户将无法创建并使用新的隐式度量值。 Report 中已有的隐式度量值仍然可以正常工作。
显式度量值
虽然隐式度量值有一些合理的使用场景,但通常更建议你创建 显式度量值。 显式度量值就是你在模型中显式定义的 DAX 度量值(或在连接的“轻量”报表中定义)。 下面的示例是上一张图中隐式度量值对应的显式度量值版本。
提示想知道某个隐式度量值采用了哪种聚合,唯一的办法是手动检查每个 Visual,或查看 Report 元数据(PBIP 中的 report.json,或 PBIX 文件,信息就存储在其中)。 这也是你可以找到 Visual Calculations 表达式的地方。 |
以下部分将更详细地介绍显式 DAX 度量值,以及在什么情况下你会选择使用它们,而不是计算列或计算表格等其他 DAX 对象。
度量值、计算列和计算表格
编写 DAX 表达式时,你可以在不同类型的对象中编写它们:度量值、计算列或计算表格。
- 度量值:包含表达式(以 DAX 编写)的定义以及属性(如说明、显示文件夹和格式)。 度量值本质上只是元数据;为了便于组织,它会关联到某个表。 度量值只有在被查询时才会计算(直接查询,或由引用它的其他度量值间接触发)。 度量值的一个例子是 Sales Amount 度量值,它用于计算所有销售额的总和 SUM。
- 计算列:包含表达式(以 DAX 编写)的定义和属性(如说明、数据类型和格式),以及计算得到的数据结果。 计算列的数据结果会让你的模型占用更多内存。 计算列在表中创建,并会对表的每一行计算其 DAX 表达式。 它们只会在刷新时计算。 计算列的一个例子是:用于标识本月有销售的新客户的标记列,你可以在其他计算中使用它。
- 计算表格:类似计算列,但其计算不依赖任何现有表和列,除了在其 DAX 表达式中引用的那些表和列。 计算表格会生成一个或多个列的独立结果。 与计算列一样,它也只会在刷新时计算。 计算表格的一个例子是:使用 CALENDAR DAX 函数创建的日期表。
注意DAX 和 Power BI 新手常问的一个问题是 我应该创建度量值还是计算列? 通常,很多新用户更喜欢计算列,因为它们会计算出结果,并且你能像在单元格和表格中立即看到反馈一样(就像 Excel 一样)。 相较之下,度量值要求你考虑该度量值将在什么上下文中被计算,以及你是否需要在计算本身中使用 CALCULATE 来修改该上下文。 在以下场景中使用计算列:
|
根据你正在构建的模型类型,你可能无法创建计算列或计算表格。 如果你的特定用例需要其中一种对象,这可能会促使你选择某一种存储模式。
下图概述了在 Power BI 目前提供的不同语义模型存储模式中,你可以创建哪些 DAX 对象。
总结一下,以下限制适用于某些类型的语义模型。 注意:存储模式是按表设置的,但 Direct Lake 例外,它不支持混合不同存储模式的表(整个模型都使用 Direct Lake 存储模式)。
- Import:将数据导入内存的模型是默认(也是最常见)的存储模式。 在这些模型中,你可以创建任意 DAX 对象。
- DirectQuery:直接连接到受支持的数据源的模型,会在运行时将 DAX 查询实时转换为等效的 SQL 查询。 这些模型不支持计算列或计算表格。
- Hybrid:包含混合存储模式或混合表格的模型,不允许在模型中的 DirectQuery 表或混合表格上创建计算列。
- Direct Lake:连接到 Fabric Lakehouse 或 Warehouse 中的 Delta 表的模型不支持计算列;并且仅在计算表格不引用 Direct Lake 表格或这些表格中的列时,才支持计算表格。 Direct Lake 仅在你拥有 Fabric capacity,并且数据以 Delta 表形式存放在 OneLake 数据项中时才可用。
注意作为本系列的一部分,我们之后会写一篇文章,帮助你理解并在不同可用的存储模式之间做出选择。 不过,这篇文章要等 Direct Lake 正式全面可用后才会发布。 |
总结
DAX 是大多数语义模型的基础组成部分。 它是一门简单而强大的语言,但也确实包含一些较为复杂的概念;要想最有效地使用它,需要一定的理论理解。 在 Power BI 解决方案的不同部分,你会结合语义模型使用 DAX 表达式或查询。 在下一篇文章中,我们会提供一些技巧和指导,帮助你在 Power BI 语义模型中高效编写 DAX。
提示如果你想深入学习 DAX,可以选择一些书籍和视频课程。 SQLBI 的 DAX 课程被视为业界标准,是学习的绝佳起点。 |

注意构建符合你数据需求的语义模型,有很多种同样可行的方法。 本系列介绍其中一种方法,并分享我们在实践中总结的技巧和最佳实践。 本系列已发布的其他文章如下:
|
图 1: 在 Tabular Editor 中,你可以在编写函数时获取相关信息,包括函数语法、说明以及文档链接。
图 7: 在 Tabular Editor 中,当你编写 DAX 时,会高亮显示行语境或语境转换等 DAX 约定,以便你更有把握地决定如何调整代码,或理解它将执行什么操作。