引言:一个每天都在发生的痛点
你是否遇到过这样的场景:业务方跑过来要一份报表,数据源是"长表"格式——每一行是一条记录,渠道、月份、金额各占一列。但领导要看的是"宽表"——月份为行,各渠道为列,一眼对比清楚。
在过去,这需要 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("""
