本文不对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对结果进行过滤。