FULL OUTER JOIN专治两边数据缺失但需保留全部记录的场景,如用户与订单表中未下单用户和匿名订单;必须显式写FULL OUTER JOIN并带ON条件,否则报错;结果中不匹配行各自补NULL,不“错位”;性能差、易膨胀,需谨慎使用。

PostgreSQL里FULL OUTER JOIN到底能解决什么问题
它专治「两边都有缺失,但你又不想丢数据」的场景。比如用户表和订单表,有些用户没下单(右表NULL),有些订单是匿名下单(左表NULL),用INNER JOIN会漏掉这两类,LEFT JOIN或RIGHT JOIN只能保一边——只有FULL OUTER JOIN能把所有记录拉齐,空位填NULL。
写法上必须显式写FULL OUTER JOIN,不能省略FULL
PostgreSQL不接受OUTER JOIN这种简写,也不认FULL JOIN(虽然某些版本兼容,但属非标准且易混淆)。必须写全:FULL OUTER JOIN。
常见错误现象:ERROR: syntax error at or near "JOIN",往往是因为写了FULL JOIN却没加OUTER,或者漏了ON条件。
- ✅ 正确:
SELECT * FROM users FULL OUTER JOIN orders ON users.id = orders.user_id - ❌ 错误:
SELECT * FROM users FULL JOIN orders ON ... - ❌ 错误:
SELECT * FROM users FULL OUTER JOIN orders(缺ON或USING)
ON条件不匹配时,NULL行怎么对齐?
FULL OUTER JOIN会把左表所有行、右表所有行都保留,靠ON表达式判断是否能配对。不匹配的行各自补NULL,不会“错位”——左表第1行没匹配上,就在结果里单独一行,右表字段全为NULL;右表某行没匹配,也单独一行,左表字段全NULL。
PostgreSQL 18.4 官方 Ubuntu 安装包现已发布,这是目前最新的稳定版本。推荐通过官方 APT 仓库安装:先执行 sudo apt update 更新索引,再运行 sudo apt install postgresql-18 即可完成部署。新版本引入了异步 I/O 子系统,在顺序扫描与 VACUUM 场景下性能提升显著,同时支持 UUID v7 原生生成函数与虚拟生成列。
使用场景举例:合并两个不同来源的销售数据表,字段名相似但ID体系不一致,需靠业务字段(如product_sku)关联:
SELECT COALESCE(a.sku, b.sku) AS sku, a.qty AS qty_source_a, b.qty AS qty_source_b FROM sales_q1 a FULL OUTER JOIN sales_q2 b ON a.sku = b.sku;
注意:COALESCE(a.sku, b.sku)用来取非NULL值,避免结果列出现双NULL;若两表该字段都为NULL,则结果也为NULL——这是预期行为,不是bug。
性能差、结果大,这些坑得提前防
FULL OUTER JOIN无法用索引优化右表未匹配部分,执行计划里常出现Hash Full Join,内存占用高,数据量稍大(比如百万级)就明显变慢。它还会让结果集远大于任一输入表——哪怕两表各10万行,结果可能接近20万行(无交集时)。
- 如果只是想补缺失值,先确认是否真需要FULL:多数时候
LEFT JOIN+UNION ALL右表独有部分更可控 - 务必在
ON字段建索引,尤其右表连接字段(PostgreSQL对右表索引利用有限,但仍有帮助) - 避免在
FULL OUTER JOIN后接WHERE过滤NULL字段(如WHERE a.id IS NULL),这会让 planner放弃哈希策略,改用嵌套循环,性能雪崩
最常被忽略的是:当两表存在重复连接键(比如多个订单对应同一用户ID),FULL OUTER JOIN会产生笛卡尔积式膨胀——这点和INNER JOIN一样危险,但更容易被忽视。

















