mcpField
P
power-query

power-query

github.com/data-goblin数据与数据库1.1k89 次安装今天更新
代码仓库

关于 power-query

power-query 是针对语义模型导入分区中 Power Query M 表达式的编写、验证与测试指南,面向模型开发者。内容涵盖查询折叠、数据预览,以及通过 API 执行或保存到模型来检查表达式。

主要功能

  1. 01编写分区 M 表达式
  2. 02指导查询折叠与性能实践
  3. 03通过 API 执行并验证结果
  4. 04预览转换步骤的数据

适用场景

  1. 01为导入表编写数据转换
  2. 02测试表达式的列名与数据类型
  3. 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.py
preview_partition.py
references/
best-practices.md
validation.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 -> SELECT
  • Table.SelectRows -> WHERE
  • Table.Sort -> ORDER BY
  • Table.FirstN -> TOP
  • Table.Group -> GROUP BY
  • Table.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 运行的完整工作流:

  1. 在工作区中创建或复用 runner 数据流
  2. 将数据源连接绑定到 runner
  3. 将表达式封装在 section 文档中,并内联参数
  4. 通过 POST /v1/workspaces/{wsId}/dataflows/{dfId}/executeQuery 执行
  5. 解析 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 参考
  • 查询折叠指南

评论

支持 Markdown