Beaver's Blog

Freedom Openness Inclusion

0%

SQL中的join

本文不对join的数学理论多做介绍,感兴趣的可以看看维基百科的解释

为什么要使用join

在关系型数据库(RDB)中,多表的关联总是没办法避免使用join。而很多初学者对于SQLjoin的用法总是搞不清楚,再加上join中类型有多种,很容易让人搞混这几种join的用法。下面我根据自己的理解,对join的用法做一个简单地介绍。

join有哪几种类型

SQL中的join大概有这几种:leftrightfullinnercross。而它们又可以分为3大类:内连接(inner join)和外连接(outer join)以及交叉连接(cross join)。其中,外连接有3种,分别是:左外连接(left outer join)、右外连接right outer join、全外连接full outer join

:在实际使用中,外连接的outer经常忽略不写

join的具体使用

我们先新建两张表:table1table2,它们的结构如下:

:本次测试使用的数据库是MySQL8.0

1
2
CREATE TABLE table1 (id int, name varchar(5) );
CREATE TABLE table2 (id int, name varchar(5) );

分别向两张表插入少量测试数据,如下:

1
2
3
4
5
6
7
8
table1				table2
id name | id name
100 'A' | 100 'A'
101 'B' | 101 'B'
102 'C' | 102 'C'
103 'D' | 103 'D'
104 'E' | 106 'G'
105 'F' | 107 'H'
  • 笛卡尔积

    在多表关联中,很多人经常使用笛卡尔积的方式进行多表关联。对于m行与n行的数据表,我们知道笛卡尔积产生的结果是mxn行数据。对于测试表table1table2,不加任何过滤条件可产生6*6=36条数据。

    1
    2
    SELECT t.*,t2.* 
    FROM table1 t, table2 t2;

    显然,对于数据量更多的表,不做好条件过滤的情况下,笛卡尔积产生的数据量将是恐怖的。巨大的数据量中,不仅很多是无效的数据,也会降低数据库的性能。因此,一般并不建议使用这种方式进行表间关联。

  • 内连接(inner join)

    对于内连接来说,只会产生符合关联条件的数据。在不使用on过滤条件的情况下,内连接产生的结果也是笛卡尔积。

    1
    2
    3
    SELECT 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
    2
    SELECT 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
    4
    SELECT t.*,t2.* 
    FROM table1 t
    LEFT JOIN table2 t2 ON t.id = t2.id
    WHERE t2.id IS NOT NULL;
  • 右连接(right join)

    在了解左连接之后,就很容易懂右连接的用法了。右连接与左连接相反,右表为主表,左表为副表。

    测试如下:

    1
    2
    3
    SELECT 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
    4
    SELECT 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对结果进行过滤。

参考文档