关于 power-query
power-query 是针对语义模型导入分区中 Power Query M 表达式的编写、验证与测试指南,面向模型开发者。内容涵盖查询折叠、数据预览,以及通过 API 执行或保存到模型来检查表达式。
主要功能
- 01编写分区 M 表达式
- 02指导查询折叠与性能实践
- 03通过 API 执行并验证结果
- 04预览转换步骤的数据
适用场景
- 01为导入表编写数据转换
- 02测试表达式的列名与数据类型
- 03检查转换步骤是否保持查询折叠
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ data-goblin/ power-bi-agentic-development --skill power-query安装后在 Claude Code 中输入/power-query确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/execute_m.pypreview_partition.pyreferences/best-practices.mdvalidation.md详细介绍
语义模型的 Power Query
编写、验证和测试语义模型导入分区中的 Power Query M 表达式。涵盖编写正确的 M 代码、保留查询折叠、验证表达式,以及通过对真实数据源执行表达式来测试。
分区表达式
语义模型中的每个导入表都有一个分区,其中的 M 表达式定义了刷新期间加载哪些数据。该表达式通常会连接到数据源、导航到某个表或视图,并应用转换。
分区表达式的结构
let
Source = Sql.Database(#"SqlEndpoint", #"Database"),
Data = Source{[Schema="dbo", Item="Orders"]}[Data],
#"Removed Columns" = Table.RemoveColumns(Data, {"InternalId"}),
#"Changed Type" = Table.TransformColumnTypes(#"Removed Columns", {{"Amount", Currency.Type}})
in
#"Changed Type"
关键元素:
- 参数:
#"SqlEndpoint"、#"Database"是在模型级别定义的共享 M 参数 - 导航:
Source{[Schema="dbo", Item="Orders"]}[Data]用于导航到特定表 - 步骤:每个步骤都是
let...in链中的一个命名变量 - 带引号的标识符:带空格的步骤名称使用
#"Step Name"语法
提取表达式
# Get partition expression from TMDL via fab
fab get "<Workspace>.Workspace/<Model>.SemanticModel" -f \
-q "definition.parts[?path=='definition/tables/<Table>.tmdl'].payload"
# Get shared M parameters
fab get "<Workspace>.Workspace/<Model>.SemanticModel" -f \
-q "definition.parts[?path=='definition/expressions.tmdl'].payload"
编写 M 表达式
查询折叠
查询折叠是最重要的性能概念。M 引擎会将兼容的步骤转换为数据源的原生查询(例如 SQL)。查询折叠中断后,后续步骤会在 mashup 引擎中运行,首先将所有数据载入内存。
通常会折叠的步骤(适用于 SQL 源):
Table.SelectColumns/Table.RemoveColumns->SELECTTable.SelectRows->WHERETable.Sort->ORDER BYTable.FirstN->TOPTable.Group->GROUP BYTable.RenameColumns->AS别名
可能折叠,也可能不折叠的步骤(取决于数据源):
Table.TransformColumnTypes——对于 SQL Server 源中的文本到数值/日期转换,经常会导致折叠中断。使用带显式转换函数(例如Number.From)的Table.TransformColumns,作为更可靠且可折叠的替代方案。
会导致查询折叠中断的步骤:
- 使用自定义 M 函数的
Table.AddColumn(无法转换为 SQL) Table.Buffer(强制物化;建议使用Table.StopFolding,在不产生内存开销的情况下停止折叠)Table.LastN(没有可替代的 SQL 语句,除非使用子查询)- 跨不同数据源使用
Table.Combine(通过EnableCrossDatabaseFolding,同一 SQL Server 内可以跨数据库折叠) - 包含 M 专属逻辑的复杂
each表达式 - 任何位于导致折叠中断的步骤之后的步骤
**最佳实践:**尽早应用兼容查询折叠的步骤(筛选、选择、类型);在所有可折叠操作完成后,再添加自定义列和仅限 M 的转换。
列裁剪和行筛选
尽早移除未使用的列并筛选行:
let
Source = Sql.Database(SqlEndpoint, Database),
Data = Source{[Schema="dbo", Item="Orders"]}[Data],
// Filter and select BEFORE any custom transforms
#"Filtered" = Table.SelectRows(Data, each [Status] <> "Cancelled"),
#"Selected" = Table.SelectColumns(#"Filtered", {"OrderId", "Date", "Amount", "CustomerId"})
in
#"Selected"
这些步骤会折叠为 SQL:SELECT OrderId, Date, Amount, CustomerId FROM dbo.Orders WHERE Status <> 'Cancelled'
类型处理
- 尽早应用
Table.TransformColumnTypes(会折叠为 SQL 中的CAST) - 使用显式 M 类型:
Int64.Type、type text、type date、Currency.Type、type logical - 避免在大型数据集中进行隐式类型推断
命名约定
- 步骤名称应描述转换内容:
#"Removed Duplicates"、#"Filtered Active" - 避免使用
#"Custom1"或#"Step1"等泛化名称 - 对带空格的步骤名称使用带引号的标识符
#"Name"(Power Query 约定)
验证 M 表达式
有两种方法可验证 M 表达式的语法是否正确,以及能否生成预期结果:
1. 通过 Power Query API 执行(推荐)
通过对真实数据运行表达式来测试。此方法可以一步验证语法、数据源连接和转换是否正确。
由随附的 examples/execute_m.py 运行的完整工作流:
- 在工作区中创建或复用 runner 数据流
- 将数据源连接绑定到 runner
- 将表达式封装在 section 文档中,并内联参数
- 通过
POST /v1/workspaces/{wsId}/dataflows/{dfId}/executeQuery执行 - 解析 Arrow 响应以验证数据
MASHUP='section Section1;
shared SqlEndpoint = "myserver.database.windows.net";
shared Database = "MyDB";
shared Result = let
Source = Sql.Database(SqlEndpoint, Database),
Data = Table.FirstN(Source{[Schema="dbo",Item="Orders"]}[Data], 10)
in Data;'
curl -s -o result.bin -X POST ".../executeQuery" \
-H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
-d "$(jq -n --arg m "$MASHUP" '{queryName:"Result",customMashupDocument:$m}')"
请参阅 references/validation.md,了解分步说明和错误处理。
2. 通过 XMLA / TOM 保存分区
将表达式写回模型;Analysis Services 会在保存时验证 M 语法。这不会执行查询,但可以捕获结构性错误:
- 缺少或不匹配的
let/in - 未定义的步骤引用
- 无效的函数调用
TransformColumnTypes中的类型不匹配
# Edit the TMDL partition source directly and deploy via fab import,
# or use the XMLA endpoint with Tabular Editor or SSMS to modify
# the partition expression on the deployed model.
如果表达式格式错误,AS 会返回错误。这比完整执行更快,但无法捕获运行时错误(列名错误、数据源问题)。
选择验证方法
| 需求 | 使用方法 |
|---|---|
| 完整数据验证(正确的列、类型、值) | 通过 API 执行 |
| 快速语法检查 | 通过 XMLA/TOM 保存到模型 |
| 逐步调试 | 使用截断的 in 子句执行 |
| 性能测试(检查折叠) | 使用完整数据执行并观察耗时 |
预览分区步骤
通过截断 let...in,查看转换链中任意位置的数据:
-- See raw source data (all columns)
in Data;
-- See after column removal
in #"Removed Columns";
-- See final result
in #"Changed Type";
对于大型表,在 in 前添加 Table.FirstN(stepName, 100),以限制行数。完整流程请参阅 references/validation.md。
常见模式
增量刷新分区
增量刷新分区使用 RangeStart 和 RangeEnd 参数:
let
Source = Sql.Database(#"SqlEndpoint", #"Database"),
Data = Source{[Schema="dbo", Item="Orders"]}[Data],
#"Filtered" = Table.SelectRows(Data, each
[OrderDate] >= #"RangeStart" and [OrderDate] < #"RangeEnd")
in
#"Filtered"
测试时,为 RangeStart 和 RangeEnd 内联具体日期值。
Lakehouse 数据源
let
Source = Lakehouse.Contents(null),
Data = Source{[Id="lakehouse-guid"]}[Data],
Table = Data{[Id="table-name", ItemKind="Table"]}[Data]
in
Table
使用原生查询的 SQL
对于无法用 M 表达的复杂 SQL:
let
Source = Sql.Database("server", "db"),
Data = Value.NativeQuery(Source, "SELECT * FROM dbo.MyView WHERE Year = 2024", null, [EnableFolding=true])
in
Data
使用 EnableFolding=true 的 Value.NativeQuery,允许后续 M 步骤在原生查询之上进行折叠。
参考资料
references/validation.md-- 详细的验证工作流,包含 executeQuery API、步骤预览和错误处理references/best-practices.md-- 查询折叠指南、折叠中断因素列表、反模式和性能技巧examples/execute_m.py-- 通过 Fabric API 执行 M 表达式的 Python 脚本(CLI 工具)examples/preview_partition.py-- 在任意步骤预览分区数据的 Python 脚本(使用fab get+execute_m.py)- Power Query M 参考
- 查询折叠指南