外连接包括 LEFT JOIN
和 RIGHT JOIN
。
MySQL 的
实现如下A
LEFT JOIN B
join_specification
表
B
被设置为依赖于表A
以及A
依赖的所有表。表
A
被设置为依赖于LEFT JOIN
条件中使用到的所有表(除了B
)。LEFT JOIN
条件用于决定如何从表B
中检索行。(换句话说,WHERE
子句中的任何条件都不使用。)执行所有标准连接优化,但始终在所有依赖的表之后读取表。如果存在循环依赖,则会发生错误。
执行所有标准
WHERE
优化。如果
A
中存在与WHERE
子句匹配的行,但B
中不存在与ON
条件匹配的行,则会生成一个额外的B
行,其所有列都设置为NULL
。如果您使用
LEFT JOIN
来查找某些表中不存在的行,并且在WHERE
部分中进行以下测试:
,其中col_name
IS NULLcol_name
是一个声明为NOT NULL
的列,那么在找到一行与LEFT JOIN
条件匹配的行之后,MySQL 将停止搜索更多行(对于特定的键组合)。
RIGHT JOIN
实现类似于 LEFT JOIN
,只是表角色相反。右连接被转换为等效的左连接,如 第 10.2.1.10 节,“外连接简化” 中所述。
对于 LEFT JOIN
,如果生成的 NULL
行对于 WHERE
条件始终为假,则 LEFT JOIN
会更改为内连接。例如,如果 t2.column1
为 NULL
,则以下查询的 WHERE
子句将为假
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;
从常量文字表达式产生的平凡 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
现在优化器可以在表 t1
之前使用表 t2
,如果这样做会导致更好的查询计划。要提供有关表连接顺序的提示,请使用优化器提示;请参阅 第 10.9.3 节,“优化器提示”。或者,使用 STRAIGHT_JOIN
;请参阅 第 15.2.13 节,“SELECT 语句”。但是,STRAIGHT_JOIN
可能阻止使用索引,因为它会禁用半连接转换;请参阅 使用半连接转换优化 IN 和 EXISTS 子查询谓词。