SQLMesh 内置宏详解:@PIVOT等常用宏的核心用法与示例
本文系统解析 SQLMesh 的四个核心内置宏,涵盖行列转换的
@PIVOT
、精准去重的@DEDUPLICATE
、灵活生成日期范围的@DATE_SPINE
,以及动态表路径解析的@RESOLVE_TEMPLATE
。通过真实案例演示参数配置与 SQL 渲染逻辑,并对比宏调用与传统 SQL 的差异,助您高效构建标准化数据处理流程。
SQLMesh 提供了一系列强大的内置宏,用于简化 SQL 查询和数据处理任务。本文将深入介绍四个常用宏:
@PIVOT
:将长格式数据转换为宽格式(行列转换)。@DEDUPLICATE
:基于分区列和排序条件去重。@DATE_SPINE
:生成日期范围表,便于时间序列分析。@RESOLVE_TEMPLATE
:动态解析表路径,适用于云存储场景。
通过实际示例,我们将展示这些宏如何提升 SQL 查询的灵活性和效率。
在这里插入图片描述
1. @PIVOT
:行列转换利器
功能概述
@PIVOT
用于将长格式数据(单列存储多个值)转换为宽格式(每行对应多个列)。常用于统计分析,如订单状态分布、用户行为分类等。
参数说明
参数 | 说明 | 默认值 |
---|---|---|
column | 要透视的列 | 必填 |
values | 用于透视的值列表 | 必填 |
alias | 是否为结果列添加别名 | true |
agg | 聚合函数(如 SUM , COUNT ) | SUM |
cmp | 比较运算符(= , > , < ) | = |
prefix / suffix | 别名前缀/后缀 | 无 |
then_value / else_value | 条件成立/不成立时的值 | 1 / 0 |
quote | 是否对别名加引号 | true |
distinct | 聚合时是否去重 | false |
示例
假设有一个 rides
表,记录骑行订单状态(cancelled
, completed
),我们希望统计每日各状态的订单数:
SQLMesh 宏写法
SELECTdate_day,@PIVOT(status, ['cancelled', 'completed'])
FROM rides
GROUP BY 1
渲染后的 SQL
SELECTdate_day,SUM(CASE WHEN status = 'cancelled' THEN 1 ELSE 0 END) AS "'cancelled'",SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) AS "'completed'"
FROM rides
GROUP BY 1
进阶用法
如果只想统计 completed
状态的订单数,并计算取消率:
SELECTdate_day,@PIVOT(status, ['completed'], agg := 'COUNT') AS completed_orders,@PIVOT(status, ['cancelled'], agg := 'COUNT') AS cancelled_orders,@PIVOT(status, ['cancelled'], agg := 'COUNT') * 1.0 / NULLIF(@PIVOT(status, ['completed'], agg := 'COUNT'), 0) AS cancellation_rate
FROM rides
GROUP BY 1
2. @DEDUPLICATE
:高效去重
功能概述
@DEDUPLICATE
使用窗口函数 ROW_NUMBER()
对数据进行去重,适用于需要保留每组最新/最旧记录的场景。
参数说明
参数 | 说明 | 示例 |
---|---|---|
relation | 表名或 CTE | my_table |
partition_by | 分区列 | [id, event_date] |
order_by | 排序条件 | ['event_date DESC', 'status ASC'] |
示例
假设 my_table
存储用户事件日志,我们希望保留每个用户每天的最新记录:
SQLMesh 宏写法
WITH raw_data AS (@DEDUPLICATE(my_table, [id, CAST(event_date AS DATE)], ['event_date DESC', 'status ASC'])
)
SELECT * FROM raw_data
渲染后的 SQL
WITH "raw_data" AS (SELECT *FROM "my_table" AS "my_table"QUALIFY ROW_NUMBER() OVER (PARTITION BY "id", CAST("event_date" AS DATE) ORDER BY "event_date" DESC, "status" ASC) = 1
)
SELECT * FROM "raw_data" AS "raw_data"
3. @DATE_SPINE
:生成日期范围表
功能概述
@DATE_SPINE
用于生成连续的日期序列,常用于时间序列分析、数据补全等场景。
参数说明
参数 | 说明 | 示例 |
---|---|---|
datepart | 时间粒度(day , week , month ) | 'day' |
start_date | 起始日期 | '2024-01-01' |
end_date | 结束日期 | '2024-01-16' |
示例
生成 2024 年 1 月 1 日至 1 月 16 日的日期表:
SQLMesh 宏写法
WITH discount_promotion_dates AS (@DATE_SPINE('day', '2024-01-01', '2024-01-16')
)
SELECT * FROM discount_promotion_dates
渲染后的 SQL(DuckDB)
WITH "discount_promotion_dates" AS (SELECT "_exploded"."date_day" AS "date_day"FROM UNNEST(CAST(GENERATE_SERIES(CAST('2024-01-01' AS DATE), CAST('2024-01-16' AS DATE), INTERVAL '1' DAY) AS DATE[])) AS "_exploded"("date_day")
)
SELECT "discount_promotion_dates"."date_day" AS "date_day"
FROM "discount_promotion_dates" AS "discount_promotion_dates"
4. @RESOLVE_TEMPLATE
:动态表路径解析
功能概述
@RESOLVE_TEMPLATE
用于动态生成表路径,适用于云存储(如 S3)或引擎元数据管理。
参数说明
参数 | 说明 | 示例 |
---|---|---|
template | 字符串模板 | 's3://bucket/@{catalog_name}/@{schema_name}/@{table_name}' |
mode | 返回类型(literal 或 table ) | literal |
示例
在模型定义中动态指定存储路径:
SQLMesh 宏写法
MODEL (name datalake.landing.customers,physical_properties (location = @resolve_template('s3://warehouse-data/@{catalog_name}/prod/@{schema_name}/@{table_name}'))
)
渲染后的 SQL
-- 生成的表路径示例:
-- s3://warehouse-data/datalake/prod/sqlmesh__landing/landing__customers__2517971505
总结
SQLMesh 的内置宏极大提升了 SQL 查询的灵活性和可维护性:
@PIVOT
简化行列转换,适用于统计分析。@DEDUPLICATE
高效去重,优化数据清洗流程。@DATE_SPINE
自动生成日期序列,简化时间序列分析。@RESOLVE_TEMPLATE
动态解析表路径,适配云存储场景。
掌握这些宏的使用方法,可以显著提升 SQL 开发效率,减少重复代码。建议在实际项目中结合业务需求灵活运用! 🚀