SQL中的各种连接join
参考:
https://www.cnblogs.com/reaptomorrow-flydream/p/8145610.html
https://www.w3school.com.cn/sql/sql_join_left.asp
https://www.w3school.com.cn/sql/sql_join.asp
https://www.cnblogs.com/yelp/p/3761443.html
https://blog.csdn.net/qq_41973536/article/details/81081024
最常见的 JOIN 类型:
1 | INNER JOIN(等价于 JOIN) |
其中第一种是内连接,后三种是外连接。
- JOIN: 内连接,又叫等值连接,只返回两个表中连接字段相等的行。(如果表中有至少一个匹配,则返回行)
- LEFT JOIN: 左连接,返回左表中所有的记录以及右表中连接字段相等的记录。(即使右表中没有匹配,也从左表返回所有的行)
- RIGHT JOIN: 右连接,返回右表中所有的记录以及左表中连接字段相等的记录。(即使左表中没有匹配,也从右表返回所有的行)
- FULL JOIN: 外连接,返回两个表中的行:left join + right join。(只要其中一个表中存在匹配,就返回行)
- cross join: 结果是笛卡尔积,就是第一个表的行数乘以第二个表的行数。
假设我们有两张表,Table A是左边的表,Table B是右边的表。
Table A:
| id | name |
|---|---|
| 1 | |
| 2 | 淘宝 |
| 3 | 微博 |
| 4 |
Table B:
| id | address |
|---|---|
| 1 | 美国 |
| 5 | 中国 |
| 3 | 中国 |
| 6 | 美国 |
1. INNER JOIN
内连接只连接匹配的行。
语法:
1 | select column_name(s) |

INNER JOIN产生的结果集,是1和2的交集。
1 | select tableA.id, name, address |
执行以上SQL输出结果如下:
| id | name | address |
|---|---|---|
| 1 | 美国 | |
| 3 | 微博 | 中国 |
等价于
1 | select tableA.id, name, address |
2. LEFT JOIN
LEFT JOIN返回左表的全部行和右表满足ON条件的行,如果左表的行在右表中没有匹配,那么这一行右表中对应数据用NULL代替。
语法:
1 | select column_name(s) |

LEFT JOIN产生表1的完全集,而2表中匹配的则有值,没有匹配的则以null值取代。
1 | select tableA.id, name, address |
执行以上SQL输出结果如下:
| id | name | address |
|---|---|---|
| 1 | 美国 | |
| 2 | 淘宝 | null |
| 3 | 微博 | 中国 |
| 4 | null |
注:若左表中一条记录匹配右表中多行,则都会返回
例:
"Persons" 表:
| Id_P | LastName | FirstName | Address | City |
|---|---|---|---|---|
| 1 | Adams | John | Oxford Street | London |
| 2 | Bush | George | Fifth Avenue | New York |
| 3 | Carter | Thomas | Changan St | Beijing |
"Orders" 表:
| Id_O | OrderNo | Id_P |
|---|---|---|
| 1 | 77895 | 3 |
| 2 | 44678 | 3 |
| 3 | 22456 | 1 |
| 4 | 24562 | 1 |
| 5 | 34764 | 65 |
1 | SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo |
结果集:
| LastName | FirstName | OrderNo |
|---|---|---|
| Adams | John | 22456 |
| Adams | John | 24562 |
| Bush | George | null |
| Carter | Thomas | 44678 |
| Carter | Thomas | 77895 |
LEFT JOIN 关键字会从左表 (Persons) 那里返回所有的行,即使在右表 (Orders) 中没有匹配的行。
3. RIGHT JOIN
RIGHT JOIN返回右表的全部行和左表满足ON条件的行,如果右表的行在左表中没有匹配,那么这一行左表中对应数据用NULL代替。
语法:
1 | select column_name(s) |

RIGHT JOIN产生表2的完全集,而1表中匹配的则有值,没有匹配的则以null值取代。
1 | select tableA.id, name, address |
执行以上SQL输出结果如下:
| id | name | address |
|---|---|---|
| 1 | 美国 | |
| 5 | null | 中国 |
| 3 | 微博 | 中国 |
| 6 | null | 美国 |
4. FULL OUTER JOIN
FULL JOIN 会从左表和右表中返回所有的行。如果其中一个表的数据行在另一个表中没有匹配的行,那么对面的数据用NULL代替。
语法:
1 | select column_name(s) |

FULL OUTER JOIN产生1和2的并集。对于没有匹配的记录,会以null做为值。
1 | select tableA.id, name, address |
执行以上SQL输出结果如下:
| id | name | address |
|---|---|---|
| 1 | 美国 | |
| 2 | 淘宝 | null |
| 3 | 微博 | 中国 |
| 4 | null | |
| 5 | null | 中国 |
| 6 | null | 美国 |
5. join中on与where的区别
数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户。
在使用left join时,on和where条件的区别如下: 1、 on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。 2、where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。
假设有两张表:
表1:table1
| id | size |
|---|---|
| 1 | 10 |
| 2 | 20 |
| 3 | 30 |
表2:table2
| size | name |
|---|---|
| 10 | AAA |
| 20 | BBB |
| 20 | CCC |
两条SQL:
1 | select * |
第一条SQL的过程:
1、中间表on条件: table1.size = table2.size
| table1.id | table1.size | table2.size | table2.name |
|---|---|---|---|
| 1 | 10 | 10 | AAA |
| 2 | 20 | 20 | BBB |
| 2 | 20 | 20 | CCC |
| 3 | 30 | (null) | (null) |
2、再对中间表过滤 where 条件: table2.name=’AAA’
| table1.id | table1.size | table2.size | table2.name |
|---|---|---|---|
| 1 | 10 | 10 | AAA |
第二条SQL的过程: 1、中间表on条件: table1.size = table2.size and table2.name=’AAA’ (条件不为真也会返回左表中的记录)
| table1.id | table1.size | table2.size | table2.name |
|---|---|---|---|
| 1 | 10 | 10 | AAA |
| 2 | 20 | (null) | (null) |
| 3 | 30 | (null) | (null) |
on条件是在left join之前先进行条件筛选,而后才对两个表格join操作。on比where起作用更早,先根据on条件进行多表的连接操作,生成一个临时表再通过where来筛选。
以上结果的关键原因在于left join,right join,full join的特殊性,不管on上的条件是否为真都会返回 left 或 right 表中的记录,full则具有left和right的特性的并集。 而inner join没这个特殊性,则条件放在on中和where中,返回的结果集是相同的。