如果你刚开始接触 Power BI,或者正在从 Excel 转型到商业智能领域,你可能会对数据模型中出现的两种主要语言感到困惑:M 和 DAX。为什么我们需要两种不同的语言?它们分别扮演什么角色?在 2026 年,随着 AI 原生开发的普及,这种分工又有了哪些新的意义?这篇文章将带你深入探讨这两大核心引擎的运作机制,我们将以第一视角的实战方式,通过具体的代码示例和应用场景,揭示它们在数据处理流程中的独特价值,并融入最新的工程化开发理念。
为什么我们需要区分 M 和 DAX?
在深入细节之前,让我们先建立一个宏观的认知。Power BI 不仅仅是一个报表工具,它是一个强大的数据转换和分析引擎。为了实现高效的数据处理,微软在 Power BI 中集成了两种截然不同的表达式语言,它们分别服务于数据生命周期的不同阶段:
- M 语言: 这是 Power Query 的原生语言。它负责“脏活累活”,即数据获取和转换(ETL)。M 语言在数据加载到模型之前运行,它的任务是清洗、重塑、合并数据,确保进入模型的数据是干净且结构化的。在现代数据工程中,我们将其视为 ELT 过程中的“E”和“T”。
- DAX (Data Analysis Expressions): 这是数据模型的血液。它负责数据分析和计算。一旦数据通过 M 语言加载到模型中,DAX 就开始工作,用于创建度量值、计算列,以及处理复杂的上下文关系。
简单来说,M 语言负责准备数据,而 DAX 负责使用数据。理解这一关键区别,是掌握 Power BI 架构的第一步。
2026 视角下的开发范式:AI 驱动的“氛围编程”
在深入具体的代码语法之前,我想先聊聊我们现在的开发环境是如何变化的。作为一名在 2026 年工作的数据开发者,我们必须习惯于“Vibe Coding”(氛围编程)。这并不意味着我们不再需要理解底层逻辑,相反,这意味着我们将繁琐的语法记忆工作交给了 AI,而我们专注于业务逻辑的解构。
我们现在经常使用像 Cursor、Copilot 或 GitHub Codespaces 这样的工具来编写 M 和 DAX。
- 实战场景: 假设我们需要从一段极其混乱的 JSON 响应中提取嵌套数据。过去我们需要查阅大量的 M 语言文档(如
Json.Document),现在我们只需在编辑器中输入注释:
// 解析这个 API 返回的 JSON,并将 ‘data.items‘ 展开为表
AI 会自动补全复杂的 INLINECODE312c1576 和 INLINECODE481fc6de 逻辑。
但是,请记住:AI 并不总是完美的。它生成的 M 代码有时会因为硬编码路径而导致“查询折叠”失效。因此,我们作为人类的角色,已经从“代码编写者”转变为“代码审核者”。我们需要理解 M 和 DAX 的执行机制,以便审查 AI 生成的代码是否符合性能最佳实践。
M 语言:数据转换的幕后英雄
M 是一种函数式编程语言,也称为 Power Query (M)。它的设计灵感借鉴了 SQL 的查询能力和 Excel 的易用性。在现代化的数据项目中,M 不仅仅是清洗工具,它是我们的数据网关。
M 语言的核心特性与企业级应用
- 多范式编程与惰性计算: M 语言结合了声明式和函数式特性。每一个查询步骤实际上都是对数据流的一次不可变操作。这种“不可变性”对于数据溯源至关重要——在企业合规性要求日益严格的 2026 年,我们不仅需要结果,更需要通过 M 的
Applied Steps(应用的步骤)完整复现数据处理的每一个逻辑节点。 - 查询折叠—— 性能的关键: 这是我们在生产环境中最为关注的概念。所谓的“查询折叠”,是指 Power Query 尝试将我们在界面中点击的操作(如筛选行、排序、移除列)尽可能翻译成源数据库的原生 SQL 语句。
* 我们遇到的坑: 在一个大型项目中,我们发现某个查询极其缓慢。经过排查,发现是因为我们在 Power Query 中添加了一步“自定义列”操作,导致 Power BI 无法将后续步骤翻译成 SQL,不得不将数百万行数据先下载到本地内存再进行计算。
* 解决方案: 我们将这部分逻辑移到了数据视图中,或者使用 SQL View 在源端解决。记住:尽量保持 M 的“纯洁性”,让数据库去做它最擅长的事。
实战演练:使用 M 处理复杂的 API 响应
让我们通过一个 2026 年常见的场景:连接 REST API 并处理分页。
场景: 我们需要从公司的 SaaS 服务获取销售数据。API 每次只返回 50 条记录,并附带一个 next_page 标记。
代码解析:
“powerquery-m
// 定义递归函数来获取所有页面
// 这种递归逻辑在处理现代 Web API 时非常常见
let
// API 基础配置
BaseUrl = "https://api.company2026.com/v1/sales",
Headers = [Authorization="Bearer " & ApiKey],
// 核心递归函数:Record 代表当前状态, 包括数据和下一页链接
FetchData = (state) =>
let
CurrentUrl = if Record.Field(state, "NextUrl") = null
then BaseUrl
else Record.Field(state, "NextUrl"),
// 发起 Web 请求
Response = Json.Document(Web.Contents(CurrentUrl, [Headers=Headers])),
NewData = Response[data],
NewNextUrl = Response[next_page], // 如果为 null 表示结束
// 更新状态:将新数据累加到旧数据中
UpdatedState = [
Data = state[Data] & NewData,
NextUrl = NewNextUrl
]
in
UpdatedState,
// 初始状态
InitialState = [Data={}, NextUrl=null],
// List.Generate 实现循环直到 NextUrl 为 null
FinalRecord = List.Generate(
() => InitialState[NextUrl] = BaseUrl, // 初始条件
each _ null, // 终止条件 (这里是简化的逻辑,实际需判断 NextUrl)
each FetchData(_) // 递归调用
),
// 将列表转换为表
OutputTable = Table.FromRecords(FinalRecord[Data])
in
OutputTable
CODEBLOCK_47b31ab4dax
// 计算列示例(通常在 Dimension 表中)
// 逻辑:根据薪资区间标记员工等级,用于切片器筛选
Employee Category =
SWITCH(
TRUE(),
‘Employee‘[Salary] > 20000, "Platinum",
‘Employee‘[Salary] > 10000, "Gold",
"Standard"
)
CODEBLOCK_a6c42ee0dax
// 度量值示例:计算年初至今 (YTD) 的总薪资
// 这是典型的“时间智能”函数应用
Total Salary YTD =
CALCULATE(
SUM(‘Employee‘[Salary]),
DATESYTD(‘Date‘[Date])
)
// 更复杂的示例:计算每个部门的薪资占比
// 需要理解 ALL 函数来修改筛选上下文
Salary % of Total =
DIVIDE(
SUM(‘Employee‘[Salary]),
CALCULATE(
SUM(‘Employee‘[Salary]),
ALL(‘Department‘) // 移除部门的筛选,计算总计
)
)
CODEBLOCK_06a88ba7dax
// 高级 DAX 示例:动态阈值过滤
High Sales Days Count =
VAR CurrentEmployeeSales = SUM(‘Sales‘[Amount])
VAR EmployeeAverage =
CALCULATE(
AVERAGEX(
VALUES(‘Date‘[Date]),
SUM(‘Sales‘[Amount])
),
ALLEXCEPT(‘Sales‘, ‘Sales‘[EmployeeID]) // 保持员工上下文,清除其他筛选
)
RETURN
IF(
CurrentEmployeeSales > EmployeeAverage,
COUNTROWS(‘Date‘),
0
)
CODEBLOCK_b3cdda08powerquery-m
let
Source = Json.Document(Web.Contents("...")),
// 如果 data 字段缺失,返回空表而不是报错
SafeData = try Record.Field(Source, "data") otherwise null,
Output = if SafeData = null then #table({}, {}) else Table.FromRecords(SafeData)
in
Output
“
总结与后续步骤
我们今天一起探索了 Power BI 中 M 语言和 DAX 的核心差异。简单回顾一下:
- M 语言 是数据的建筑师。它在后台默默工作,负责清洗、重塑数据,通过声明式的步骤将杂乱的数据源转化为结构化的数据表。在 AI 辅助开发时代,它是处理非结构化数据源的利器。
- DAX 是数据的分析师。它在前台展示智慧,基于用户的交互,利用数据模型中的关系进行复杂的聚合计算和逻辑判断。掌握上下文转换是精通它的关键。
掌握了这两者的分工,你就已经具备了构建复杂商业智能模型的基础。对于你的下一步学习,我们建议你深入尝试以下操作:
- 拥抱 AI 工具: 让 AI 帮你生成基础代码,然后你逐行审查,特别是关注“查询折叠”和“上下文转换”这两个核心概念。
- 重构思维: 从“面向过程”的 Excel 思维转向“面向模型”的 BI 思维。不要总想着在 M 里算出所有东西,也不要总想着在 DAX 里做行级别的清洗。
- 探索 Fabric: 微软的 Power BI 现在已深度整合进 Microsoft Fabric。了解你的 DAX 如何在 Fabric 的 Direct Lake 模式下运行,这是未来的方向。
Power BI 的世界非常广阔,M 和 DAX 是开启这个世界的两把钥匙。保持好奇心,多动手实验,你会发现处理数据不再是枯燥的工作,而是一种创造价值的乐趣。