引言:一个每天都在发生的痛点
你是否遇到过这样的场景:业务方跑过来要一份报表,数据源是"长表"格式——每一行是一条记录,渠道、月份、金额各占一列。但领导要看的是"宽表"——月份为行,各渠道为列,一眼对比清楚。
在过去,这需要 Python + Pandas:写 pivot() 或 groupby().unstack(),处理缺失值,调试索引……一套流程下来,半小时起步。
今天我们来聊聊 DuckDB 的原生 PIVOT/UNPIVOT 语法。一条 SQL 搞定,零依赖,性能还比 Pandas 快 10 倍以上。
一、PIVOT:长表转宽表
1.1 基础语法
DuckDB 的 PIVOT 语法非常直观:
PIVOT table_name
ON pivot_column
USING aggregate_function(value_column)
GROUP BY group_columns;
1.2 完整实战示例
假设你有以下销售数据(长表格式):
| month | channel | amount |
|--------|---------|--------|
| 2026-01 | 天猫 | 150000 |
| 2026-01 | 京东 | 98000 |
| 2026-01 | 抖音 | 220000 |
| 2026-02 | 天猫 | 180000 |
| 2026-02 | 京东 | 110000 |
| 2026-02 | 抖音 | 195000 |
| 2026-03 | 天猫 | 205000 |
| 2026-03 | 京东 | 125000 |
| 2026-03 | 抖音 | 240000 |
一条 SQL 转换为宽表:
PIVOT sales
ON channel
USING SUM(amount)
GROUP BY month;
输出结果:
| month | 天猫 | 京东 | 抖音 |
|--------|--------|--------|--------|
| 2026-01 | 150000 | 98000 | 220000 |
| 2026-02 | 180000 | 110000 | 195000 |
| 2026-03 | 205000 | 125000 | 240000 |
1.3 Python 完整代码
import duckdb
con = duckdb.ATTACH ("ecommerce.db")
# 创建测试数据
con.execute("""
---
## 本文信息
| 项目 | 内容 |
|------|------|
| DuckDB 版本 | v1.5.x(部分功能基于 v2.0 Preview) |
| 最后验证 | 2026-09-12 |
| 测试环境 | Linux / x86_64 / 16GB RAM |
| 官方文档 | [DuckDB Documentation](https://duckdb.org/docs/) |
| GitHub | [pengzz9527/duckdb-blog](https://github.com/pengzz9527/duckdb-blog) |
如发现错误,欢迎通过 [GitHub Issue](https://github.com/pengzz9527/duckdb-blog/issues) 或邮件 [email protected] 反馈。
