版本比较
标识
- 该行被添加。
- 该行被删除。
- 格式已经改变。
使用学生表和成绩表来演示连接,SQL架构如下:
代码块 | ||||
---|---|---|---|---|
| ||||
Create table If Not Exists student_info (id int, name varchar(255));
Create table If Not Exists student_score (id int, score int);
Truncate table student_info;
insert into student_info (id, name) values ('1', 'Wang');
insert into student_info (id, name) values ('2', 'Alice');
insert into student_info (id, name) values ('3', 'Allen');
Truncate table student_score;
insert into student_score (id, score) values ('1', '65');
insert into student_score (id, score) values ('2', '70');
insert into student_score (id, score) values ('3', '75'); |
注意id为3的学生没有成绩记录,如下:执行连接查询的语句如下:
代码块 | ||||
---|---|---|---|---|
| ||||
mysql> SELECT * FROM student_score, student_info; +------+-------+ | id | name | +------+-------+ | id 1 | Wang score | | id 2 | name Alice | | 3 | Allen | +------+-------+ 3 rows in set (0.00 sec) mysql> SELECT * FROM student_score; +------+-------+ | id 3 | 75 score | +------+-------+ | 1 | Wang 65 | | 2 | 70 | +------+-------+ 2 rows in set (0.00 sec) |
执行一次典型的外连接查询,查询所有学生的成绩,不管其有没有成绩记录,如下:
代码块 |
---|
mysql> SELECT * FROM student_info LEFT JOIN student_score ON student_info.id = student_score.id; +------+-------+------+-------+ | id | name | id | score | +------+-------+------+-------+ | 1 | Wang | 1 | Wang | | 1 | 65 | 1 | Wang | | 3 | 75 | 2 | Alice | | 2 | 70 | 2 | Alice | | 1 | 65 | | 2 | Alice | | 3 | 752 | 370 | Allen | | 2 | 70 | 3 | Allen | | 1 NULL | 65 | 3 | Allen |NULL | +------+-------+------+-------+ 93 rows in set (0.00 sec) |
上面的连接查询直接把多表放在了FROM后面,用逗号进行间隔,所以是内连接,与下面的语句是等效的:
以下是关于外连接和ON的一些解释。
以左外连接为例,左外连接的目的是取出左表的每一行,然后和右表的所有行进行匹配,如果有符合ON条件的行,就输出组合后的结果,如果右表遍历后连没有一条符合ON条件的记录,就用NULL
值替代右表,再进行组合后输出。
如果ON条件设置为1,也就是无论左表的记录是什么,右表的所有行都符合条件,那么外连接的查询就和笛卡尔积是等价的,如下:
代码块 | |
---|---|
代码块 | |
language | sql | theme | DJango
mysql> SELECT * FROM student_info LEFT JOIN student_score ON 1; +------+-------+------+-------+ | id | name | id | score | +------+-------+------+-------+ | 3 | Allen | 1 | Wang 65 | | 2 | Alice | 1 | 6570 | | 1 | Wang | 1 | 65 | | 32 | AllenAlice | 2 | 70 | | 2 | Alice | 21 | 7065 | | 13 | WangAllen | 2 | 70 | | 3 | Allen | 3 | 75 | | 2 | Alice | 3 | 75 | | 1 | Wang | 365 | 75 | +------+-------+------+-------+ 96 rows in set (0.00 sec) |
从结果来推导一下连接的行为。
首先,连接的关键字是join
,join
是一个及物动词,比如A join B
,字面上的意思就是A加入B,或者说A成为B的一员,这里B是主导,而A是次要。
回到SQL中的join
。SQL在生成连接时,默认生成的是笛卡儿积,也就是一个表中的每条记录都和另一个表中的所有记录组合一次。这里到底是先取哪个表,就是根据join来定的。比如student_info JOIN student_score
,这种写法下,student_score
表是主导,student_info
表负责“加入”student_score
表,所以先取的记录来自于student_score
表中,这也可以通过上面的结果得到验证。来自student_score
表的列虽然位于结果集的右侧,但是记录是
外连接一定要on,参考:https://cloud.tencent.com/developer/ask/206061
参考:
SQL JOIN Types Explained | LearnSQL.com在外连接中,ON子句是必需的,不能省略。比如左外连接,生成的结果集一定包含左表的所有行,而对于右表取哪些行,就通过ON子句来指定,注意这里的ON子句的结果已经不重要了,重要的是ON子句指定了右表如何匹配左表。
贴一张图以助于理解:
Image Added
目录 |
---|