TOC

SQL Join

标准

graph TD

join(JOIN)
inner(INNER JOIN)
outer(OUTER JOIN)
cross(CROSE JOIN)
left(LEFT OUTER JOIN)
right(RIGHT OUTER JOIN)
full(FULL OUTER JOIN)

join-->inner
join-->outer
join-->cross

outer-->left
outer-->right
outer-->full

上面是 SQL 标准中规定的五种 JOIN 方式,
- SQLServer (T-SQL) 都支持,
- Oracle (PL/SQL) 可能也是,
- SQLite 只支持 CROSS JOIN, INNER JOIN, OUTER JOIN (左外连接);
- MySQL:
1. MySQL 的 Join 默认是 Inner Join
1. Outer Join 中可以省略 Outer,但是 Left 和 Right 必须写
1. 没有 Full Join

基本用法

实际上用的多的是以下三种:

  • [INNER] JOIN
  • LEFT [OUTER]
  • RIGHT [OUTER]

内连接 (inner)

SELECT * FROM `user` JOIN `order` ON `user`.`id` = `order`.`user_id`

左连接 (left)

SELECT * FROM `order` LEFT JOIN `user` ON `user`.`id` = `order`.`user_id`

右连接 (right)

SELECT * FROM `user` LEFT JOIN `order` ON `user`.`id` = `order`.`user_id`

全连接 (full)

用的少。

在 MySQL 中可以采用左连接 UNIOIN 右连接的方式来实现。

-- 移除重复行
SELECT * FROM `user` LEFT JOIN `order` ON `user`.`id` = `order`.`user_id`
UNION
SELECT * FROM `user` RIGHT JOIN `order` ON `user`.`id` = `order`.`user_id`

-- 不移除重复行
SELECT * FROM `user` LEFT JOIN `order` ON `user`.`id` = `order`.`user_id`
UNION ALL
SELECT * FROM `user` RIGHT JOIN `order` ON `user`.`id` = `order`.`user_id` WHERE `user`.`id` IS NULL

交叉连接 (cross)

返回两张表的笛卡尔积,不需要 ON 子句,我还没有在业务中遇到过需要交叉的场景。

直接连接 (straight)

和 INNER JOIN 一个意思,不过就是可以指定优先查询速度 —— 左表先读,根据左表满足条件的部分再来 JOIN 右表。
部分情况下可以优化查询速度,比如说,根据左表索引快速命中部分数据,或者左表数据量不大,那么优先使用左边的数据能够减少很多不必要的计算量。

STRAIGHT_JOIN is similar to JOIN, except that the left table is always read before the right table. This can be used for those (few) cases for which the join optimizer processes the tables in a suboptimal order.

自然连接 (natural)

NATURAL [{LEFT|RIGHT} [OUTER]] JOIN

支持 inner, outer 前面加上了 natural 前缀。

在相同列(名称 + 类型)上做连接,省掉 ONUsing

参考资料与拓展阅读