mysql不支持full join,官方明确未实现该语法,必须用left join与right join结果集通过union all合并模拟:先取左表全量+右表匹配行,再补右表独有行(where左表关联字段is null),并确保字段顺序、类型、别名严格一致。

MySQL不支持FULL JOIN,必须用LEFT JOIN + RIGHT JOIN组合
MySQL从8.0到最新版都**没有实现FULL JOIN语法**,直接写会报错:ERROR 1064 (42000): You have an error in your SQL syntax。这不是版本问题,是官方明确不支持的特性。想达到全连接效果,唯一可靠方式是用LEFT JOIN和RIGHT JOIN结果集UNION ALL合并,并排除重复的交集行。
正确构造FULL JOIN等价SQL的三步写法
核心思路:先取左表全量+右表匹配行(LEFT JOIN),再补上右表有、左表无的行(RIGHT JOIN WHERE 左表主键 IS NULL)。注意必须用UNION ALL而非UNION,避免隐式去重影响性能。
- 第一步:写出标准
LEFT JOIN,关联条件与你设想的FULL JOIN一致,例如ON a.id = b.user_id - 第二步:写出对应
RIGHT JOIN,但WHERE里限制左表关联字段为NULL,例如WHERE a.id IS NULL - 第三步:用
UNION ALL拼接两个结果,确保两部分SELECT字段顺序、类型、别名完全一致
示例(连接users和orders):
SELECT u.id, u.name, o.order_id FROM users u LEFT JOIN orders o ON u.id = o.user_id UNION ALL SELECT u.id, u.name, o.order_id FROM users u RIGHT JOIN orders o ON u.id = o.user_id WHERE u.id IS NULL;
LEFT JOIN + RIGHT JOIN组合的坑:NULL值和重复字段处理
这个写法表面简单,但实际容易出错的关键点在NULL和字段对齐上:
- 如果关联字段本身允许NULL,
WHERE u.id IS NULL可能误判——务必确认该字段在业务中不会存NULL,否则要改用NOT EXISTS子查询替代RIGHT JOIN部分 -
UNION ALL要求两侧列数、类型、顺序严格一致,若某侧SELECT多了一个计算字段(如COUNT(*)),会直接报错ERROR 1222 (21000): The used SELECT statements have a different number of columns - 当两表有同名字段(如都叫
created_at),必须显式用别名区分,否则UNION ALL后字段名不可控
性能比原生FULL JOIN差很多,大数据量时务必加索引
MySQL执行这种等价写法时,会分别跑两次JOIN再合并结果,IO和CPU开销接近两倍。特别是RIGHT JOIN ... WHERE left_key IS NULL这部分,如果没有在关联字段上建索引,很容易触发全表扫描。
- 必须确保
ON条件中的字段(如users.id、orders.user_id)都有单列索引或联合索引 - 如果
RIGHT JOIN部分数据量远大于LEFT JOIN,可以考虑把小表放左边,用LEFT JOIN两次(一次正向、一次反向)来减少驱动表扫描量 - 500万行以上数据时,建议先用
EXPLAIN看执行计划,重点关注type是否为ref或eq_ref,避免出现ALL
真正难的不是写出来,而是验证它确实返回了预期的全集——尤其当任一表存在NULL关联值或重复键时,结果可能比想象中少或多几行。











