外连接包括LEFT JOIN
和
RIGHT JOIN
。
MySQL 实现如下:
A
LEFT
JOIN B
join_specification
表
B
被设置为依赖于表A
和依赖于它的所有表A
。表
A
设置为依赖于条件B
中使用的所有表(除了 )LEFT JOIN
。LEFT JOIN
条件用于决定如何从表中检索 行B
。(换句话说,WHERE
不使用子句中的任何条件。)执行所有标准连接优化,但始终在读取它所依赖的所有表之后读取表除外。如果存在循环依赖,则会发生错误。
执行所有标准
WHERE
优化。如果其中有与子句
A
匹配的行WHERE
,但没有与条件B
匹配的 行,则会生成ON
一个额外的 行,并将所有列设置为。B
NULL
如果你
LEFT JOIN
用来查找某个表中不存在的行,并且你有以下测试:
在col_name
IS NULLWHERE
部分中,wherecol_name
是一个声明为的列NOT NULL
,MySQL 在找到后停止搜索更多行(对于特定的键组合)符合LEFT JOIN
条件 的一行。
RIGHT JOIN
实现类似于LEFT JOIN
表角色颠倒
的实现。右连接转换为等效的左连接,如第 8.2.1.10 节“外部连接简化”中所述。
对于 a LEFT JOIN
,如果
生成的行的WHERE
条件始终为假,则将更改为内部联接。例如,如果是,则该
子句
在以下查询中将为假:
NULL
LEFT
JOIN
WHERE
t2.column1
NULL
SELECT * FROM t1 LEFT JOIN t2 ON (column1) WHERE t2.column2=5;
因此,将查询转换为内部联接是安全的:
SELECT * FROM t1, t2 WHERE t2.column2=5 AND t1.column1=t2.column1;
在 MySQL 8.0.14 及更高版本中,WHERE
由常量文字表达式引起的琐碎条件在准备期间被删除,而不是在优化的后期阶段被删除,到那时连接已经被简化。早期删除琐碎的条件允许优化器将外部连接转换为内部连接;这可以改进在子句中包含简单条件的外部连接的查询计划WHERE
,例如:
SELECT * FROM t1 LEFT JOIN t2 ON condition_1 WHERE condition_2 OR 0 = 1
优化器现在在准备过程中发现 0 = 1 始终为假,因此变得OR 0 = 1
多余,并将其删除,留下:
SELECT * FROM t1 LEFT JOIN t2 ON condition_1 where condition_2
现在优化器可以将查询重写为内部连接,如下所示:
SELECT * FROM t1 JOIN t2 WHERE condition_1 AND condition_2
现在优化器可以在表t2
之前使用表,t1
如果这样做会产生更好的查询计划。要提供有关表连接顺序的提示,请使用优化器提示;参见
第 8.9.3 节,“优化器提示”。或者,使用
STRAIGHT_JOIN
; 参见
第 13.2.10 节,“SELECT 语句”。但是,
STRAIGHT_JOIN
可能会阻止使用索引,因为它会禁用半连接转换;参见
第 8.2.2.1 节,“使用半连接转换优化 IN 和 EXISTS 子查询谓词”。