本文不对join
的数学理论多做介绍,感兴趣的可以看看维基百科的解释。
为什么要使用join
在关系型数据库(RDB)
中,多表的关联总是没办法避免使用join
。而很多初学者对于SQL
中join
的用法总是搞不清楚,再加上join
中类型有多种,很容易让人搞混这几种join
的用法。下面我根据自己的理解,对join
的用法做一个简单地介绍。
join有哪几种类型
SQL
中的join
大概有这几种:left
、right
、full
、inner
和cross
。而它们又可以分为3大类:内连接(inner join)
和外连接(outer join)
以及交叉连接(cross join)
。其中,外连接有3种,分别是:左外连接(left outer join)
、右外连接right outer join
、全外连接full outer join
。
注:在实际使用中,外连接的outer
经常忽略不写
join的具体使用
我们先新建两张表:table1
和table2
,它们的结构如下:
注:本次测试使用的数据库是MySQL8.0
1 | CREATE TABLE table1 (id int, name varchar(5) ); |
分别向两张表插入少量测试数据,如下:
1 | table1 table2 |
笛卡尔积
在多表关联中,很多人经常使用笛卡尔积的方式进行多表关联。对于
m
行与n
行的数据表,我们知道笛卡尔积产生的结果是mxn
行数据。对于测试表table1
和table2
,不加任何过滤条件可产生6*6=36
条数据。1
2SELECT t.*,t2.*
FROM table1 t, table2 t2;显然,对于数据量更多的表,不做好条件过滤的情况下,笛卡尔积产生的数据量将是恐怖的。巨大的数据量中,不仅很多是无效的数据,也会降低数据库的性能。因此,一般并不建议使用这种方式进行表间关联。
内连接
(inner join)
对于内连接来说,只会产生符合关联条件的数据。在不使用
on
过滤条件的情况下,内连接产生的结果也是笛卡尔积。1
2
3SELECT t.*,t2.*
FROM table1 t
INNER JOIN table2 t2 ON t.id=t2.id;结果如下:
id name id name 100 A 100 A 101 B 101 B 102 C 102 C 103 D 103 D 从上面的结果,我们也可以看出,产生的结果只含有
table1.id
等于table2.id
的数据。左连接
(left join)
在左连接中,左表称为主表,而右表称为副表。不加过滤的情况下,连接不仅会产生符合连接条件的数据,也会全部产生左表的数据。
1
2SELECT t.*,t2.* FROM table1 t
LEFT JOIN table2 t2 ON t.id = t2.id;结果如下:
id name id name 100 A 100 A 101 B 101 B 102 C 102 C 103 D 103 D 104 E 105 F 根据上面结果,能看来左连接与内连接不一样的是:左连接不仅会产生符合连接条件的数据,不符合连接条件的左表数据也会在结果中,由于右表存在不符合关联条件的数据,则结果中右表数据都是
NULL
。有意思的是,将左连接SQL
代码改成下面这样,产生的结果将会和内连接是一样的。1
2
3
4SELECT t.*,t2.*
FROM table1 t
LEFT JOIN table2 t2 ON t.id = t2.id
WHERE t2.id IS NOT NULL;右连接
(right join)
在了解左连接之后,就很容易懂右连接的用法了。右连接与左连接相反,右表为主表,左表为副表。
测试如下:
1
2
3SELECT t.*,t2.*
FROM table1 t
RIGHT JOIN table2 t2 ON t.id = t2.id;结果如下:
id name id name 100 A 100 A 101 B 101 B 102 C 102 C 103 D 103 D 106 G 107 H 同样地,将代码改成下面这样,也能得到与内连接一样的结果,注意这次是过滤条件是左表的
id is not null
。1
2
3
4SELECT t.*,t2.*
FROM table1 t
RIGHT JOIN table2 t2 ON t.id = t2.id
WHERE t.id IS NOT NULL;全外连接
(full join)
如果说左连接与右连接是“相反的”,那么全外连接更像是左右连接的”并集“。不仅会输出符合关联条件的数据,左表右表不符合关联条件的数据也会一并给出,只不过对于左、右表中不符合关联条件的数据,对方位置也是以
NULL
显示的。注:目前
mysql
还不支持全外连接的用法结果如下:
id name id name 100 A 100 A 101 B 101 B 102 C 102 C 103 D 103 D 104 E 105 F 106 G 107 H 对于结果就不多做解释了。
交叉连接
(cross join)
在标准
SQL
中,[CROSS|INNER] JOIN
在没有使用on
的情况下产生的结果都是笛卡尔积,需要使用on
对结果进行过滤。