Excel 用户每天都在做”两表合并”——订单表 + 客户表,把客户名替换 ID;销售流水 + 商品库,加上分类。Excel 的标配解决方案是 VLOOKUP / INDEX-MATCH / Power Query:
- VLOOKUP 单条匹配可以,但条件超过 1 个、嵌套超过 2 层就开始踩坑——参数顺序记不住,相对引用 / 绝对引用一不小心就错位
- INDEX-MATCH 比 VLOOKUP 灵活但语法更绕,新手学不会
- Power Query 能做合并查询但操作链不可读——20 步操作交给同事,他得逐步点开看,改一步可能让下游全断
SQL 是这件事最自然的工具——它就是为”多表关联 + 聚合”设计的语言。问题只是 SQL 一直跟”安装数据库 + Python + pandas”绑定,普通 Excel 用户够不着。
DuckDB SQL 查询台 把这个鸿沟填上了:把 .xlsx 拖到浏览器里,每个 sheet 变成一张 SQL 表,立刻能 JOIN / 聚合 / 透视。底层用 SheetJS(解 xlsx)+ DuckDB-Wasm(OLAP 引擎),都跑在浏览器本地,文件不出电脑。
5 个高频实战场景
1. 把客户 ID 替换成客户名(VLOOKUP 替代)
orders sheet 里只有 customer_id,想让结果直接显示客户名 + 城市——Excel 要写两个 VLOOKUP:
=VLOOKUP(B2, customers!A:E, 2, FALSE) ' 客户名
=VLOOKUP(B2, customers!A:E, 4, FALSE) ' 城市
SQL 一行:
SELECT
o.order_id,
o.amount,
c.name AS customer_name,
c.city AS customer_city,
o.order_date
FROM orders o
JOIN customers c ON o.customer_id = c.id
ORDER BY o.order_date DESC
LIMIT 100;
o、c 是别名,让后面引用列时不用重复写整个表名。
2. 找漏匹配的订单(LEFT JOIN + IS NULL)
订单里有些 customer_id 在客户主数据里查不到——可能是数据质量问题。Excel 要 IFERROR(VLOOKUP(...), "缺失") 然后筛选;SQL 一句更直接:
SELECT o.order_id, o.customer_id, o.amount
FROM orders o
LEFT JOIN customers c ON o.customer_id = c.id
WHERE c.id IS NULL; -- 客户主数据里没匹配上的订单
LEFT JOIN 保留所有订单,匹配不上的客户字段为 NULL,再过滤 c.id IS NULL 就拿到所有”漏匹配”行。
3. 跨 sheet 汇总同比(UNION ALL + 条件聚合)
Q1 / Q2 两个 sheet,想算各区域季度环比:
WITH all_q AS (
SELECT 'Q1' AS quarter, * FROM sales_q1
UNION ALL
SELECT 'Q2', * FROM sales_q2
)
SELECT
region,
SUM(total) FILTER (WHERE quarter = 'Q1') AS q1_gmv,
SUM(total) FILTER (WHERE quarter = 'Q2') AS q2_gmv,
ROUND(
(SUM(total) FILTER (WHERE quarter = 'Q2'))
/ NULLIF(SUM(total) FILTER (WHERE quarter = 'Q1'), 0) * 100 - 100,
1
) AS qoq_pct
FROM all_q
GROUP BY region
ORDER BY q2_gmv DESC;
FILTER (WHERE ...) 是”条件聚合”——比 SUM(CASE WHEN quarter='Q1' THEN total ELSE 0 END) 简洁得多。Excel 里要做同样的事,得先用透视表分别算两个 quarter,然后用辅助列做除法,至少 3 步。
4. 多对多关联(订单 × 商品 × 类目)
SELECT
c.category_name,
COUNT(*) AS orders,
SUM(o.qty * p.price) AS revenue,
SUM(o.qty) AS units
FROM orders o
JOIN products p ON o.product_id = p.id
JOIN categories c ON p.category_id = c.id
WHERE o.order_date BETWEEN '2026-04-01' AND '2026-04-30'
GROUP BY c.category_name
ORDER BY revenue DESC;
3 个 sheet 同时 JOIN——Excel 要套 3 层 VLOOKUP + SUMIFS,公式长到一行写不完;SQL 缩进对齐之后非常清楚每张表用谁的什么字段。
5. 找每个区域销售 Top 3(窗口函数 + QUALIFY)
SELECT
region,
salesperson,
total
FROM sales
QUALIFY ROW_NUMBER() OVER (
PARTITION BY region
ORDER BY total DESC
) <= 3
ORDER BY region, total DESC;
QUALIFY 是 DuckDB / Snowflake 的便利语法——窗口函数版本的 WHERE,不需要套子查询。Excel 里这种”分组取 Top N”要么排序后人工筛、要么用复杂的数组公式 LARGE + INDEX-MATCH,SQL 直接表达”每组排名前 3”。
VLOOKUP / Power Query → SQL 速查
| Excel 写法 | SQL 等价 |
|---|---|
VLOOKUP(A2, t!A:B, 2, FALSE) | INNER JOIN ... ON a = b |
IFERROR(VLOOKUP(...), "") | LEFT JOIN ...(缺失行 = NULL) |
数组公式 SUMIFS | SUM(x) FILTER (WHERE ...) GROUP BY ... |
| 透视表 | GROUP BY + PIVOT(DuckDB 支持原生 PIVOT 语法) |
| Power Query「合并查询」 | JOIN |
| Power Query「追加查询」 | UNION ALL |
| Power Query「分组依据 → 求和」 | GROUP BY ... SUM(...) |
INDEX(MATCH(...), ...) | JOIN 或子查询 |
嵌套 IF | CASE WHEN ... THEN ... ELSE ... END |
何时还是回 Excel 自己处理
SQL 不是万金油——以下场景 Excel 仍然更合适:
- 小数据 + 一次性:5 行 × 3 列的数据写 SQL 不如点几下 Excel
- 要带着格式给老板:颜色、边框、合并单元格、批注——Excel 原生支持,SQL 输出后还要回 Excel 美化
- 公式依赖原 sheet 内动态变化:业务同事想”改了 A 列让 B 列实时变”——这是 Excel 的强项,SQL 是一次性查询
- 数据透视图 / 切片器:Excel 透视图的交互探索能力 SQL 短期内追不上
真正能用 SQL 替代 Excel 的场景:(1) 多 sheet 跨表合并;(2) 聚合 + 关联同时做;(3) 数据质量自检;(4) 给下游交付 CSV/Parquet。
隐私 + 不上传
整个工具没有后端——文件用 File.arrayBuffer() 读到内存,SheetJS 在 Web Worker 解析成 CSV bytes,直接喂给 DuckDB-Wasm。可以断网用,可以打开 DevTools Network 面板验证。适合敏感数据:客户订单、未脱敏的 KOL 流水、内部财务表,都不会离开你的电脑。
DuckDB-Wasm 引擎本身(约 35 MB wasm)从同源静态资源加载一次,之后浏览器缓存命中。SheetJS 用的是开源 @sheet/xlsx 社区版,pure JS,无依赖。
配套链路
- 想直接看 .parquet 文件结构(不写 SQL),用更轻量的 Parquet 在线预览(hyparquet 50 KB,秒开)
- SQL 跑完想格式化、压缩、加注释,用 代码格式化(含 sql-formatter)
- 跑完导出的 CSV 想转 JSON / YAML / XML,用 YAML/CSV/XML 互转