MySQL 连接表
最后修改于 2023 年 1 月 10 日
在本 MySQL 教程中,我们将连接 MySQL 中的表。
从关系数据库获得真正力量和好处来自于连接表。 SQL JOIN 子句组合数据库中两个或多个表的记录。 基本上有两种类型的连接:INNER 和 OUTER。
在本教程中,我们将使用 Customers 和 Reservations 表。
mysql> SELECT * FROM Customers; +------------+-------------+ | CustomerId | Name | +------------+-------------+ | 1 | Paul Novak | | 2 | Terry Neils | | 3 | Jack Fonda | | 4 | Tom Willis | +------------+-------------+
这些是 Customers 表中的值。
mysql> SELECT * FROM Reservations; +----+------------+------------+ | Id | CustomerId | Day | +----+------------+------------+ | 1 | 1 | 2009-11-22 | | 2 | 2 | 2009-11-28 | | 3 | 2 | 2009-11-29 | | 4 | 1 | 2009-11-29 | | 5 | 3 | 2009-12-02 | +----+------------+------------+
这些是 Reservations 表中的值。
Customers 和 Reservations 都有一个 CustomerId 列。 它是关系列。 如果它在两个表中具有相同的名称,我们可以使用 USING (CustomerId) 语法。 如果名称不同,例如我们有 CustomerId 和 CId,我们将使用 ON Customers.CustomerId = Reservations.CId 语法。
MySQL 内连接
内连接是最常见的连接类型。 它也是默认的连接。 内连接仅选择数据库表中具有匹配值的那些记录。 我们有三种类型的 INNER JOINS:INNER JOIN、NATURAL INNER JOIN 和 CROSS INNER JOIN。 INNER 关键字可以省略。
INNER JOIN
mysql> SELECT Name, Day FROM Customers AS C JOIN Reservations
-> AS R ON C.CustomerId=R.CustomerId;
+-------------+------------+
| Name | Day |
+-------------+------------+
| Paul Novak | 2009-11-22 |
| Terry Neils | 2009-11-28 |
| Terry Neils | 2009-11-29 |
| Paul Novak | 2009-11-29 |
| Jack Fonda | 2009-12-02 |
+-------------+------------+
5 rows in set (0.00 sec)
在此 SELECT 语句中,我们选择了所有已进行预订的客户。 Paul Novak 和 Terry Neils 进行了两次预订。 Jack Fonda 进行了一次。 Tom Willis 缺席,他还没有进行任何预订。 请注意,我们省略了 INNER 关键字。
该语句等效于以下语句
mysql> SELECT Name, Day FROM Customers, Reservations
-> WHERE Customers.CustomerId=Reservations.CustomerId;
+-------------+------------+
| Name | Day |
+-------------+------------+
| Paul Novak | 2009-11-22 |
| Terry Neils | 2009-11-28 |
| Terry Neils | 2009-11-29 |
| Paul Novak | 2009-11-29 |
| Jack Fonda | 2009-12-02 |
+-------------+------------+
我们得到相同的数据。
CROSS INNER JOIN
CROSS INNER JOIN 将一个表中的所有记录与另一个表中的所有记录组合起来。 这种类型的连接几乎没有实际价值。 它也被称为记录的笛卡尔积。
mysql> SELECT Name, Day FROM Customers CROSS JOIN Reservations; +-------------+------------+ | Name | Day | +-------------+------------+ | Paul Novak | 2009-11-22 | | Paul Novak | 2009-11-28 | | Paul Novak | 2009-11-29 | | Paul Novak | 2009-11-29 | | Paul Novak | 2009-12-02 | | Terry Neils | 2009-11-22 | | Terry Neils | 2009-11-28 | | Terry Neils | 2009-11-29 | | Terry Neils | 2009-11-29 | | Terry Neils | 2009-12-02 | | Jack Fonda | 2009-11-22 | ...
可以使用以下 SQL 语句实现相同的结果
SELECT Name, Day FROM Customers, Reservations;
MySQL 外连接
一个 外连接 并不要求两个连接表中的每条记录都有匹配的记录。 外连接有三种类型。 左外连接、右外连接和全外连接。 在本教程创建时,MySQL 不支持全外连接。
正如我们上面已经提到的,内连接是最常见的。 外连接可能有助于找出孤立记录。 如果一个人没有进行任何预订,他还是客户吗? 如果我们无法将其与客户匹配,那么预订有效吗?
LEFT OUTER JOIN
LEFT OUTER JOIN 返回左表中的所有值,即使与右表不匹配。 在此类行中,将有 NULL 值。 换句话说,左外连接返回左表中的所有值,加上右表中的匹配值。 请注意,可以省略 OUTER 关键字。
mysql> SELECT Name, Day FROM Customers LEFT JOIN Reservations
-> ON Customers.CustomerId=Reservations.CustomerId;
+-------------+------------+
| Name | Day |
+-------------+------------+
| Paul Novak | 2009-11-22 |
| Paul Novak | 2009-11-29 |
| Terry Neils | 2009-11-28 |
| Terry Neils | 2009-11-29 |
| Jack Fonda | 2009-12-02 |
| Tom Willis | NULL |
+-------------+------------+
在这里,我们有所有客户及其预订,以及一个没有预订的客户。 他的行中有一个 NULL 值。
我们可以使用 USING 关键字来实现相同的结果。 这是因为关系列在两个表中具有相同的名称。 SQL 语句将不太冗长。
mysql> SELECT Name, Day FROM Customers LEFT JOIN Reservations
-> USING (CustomerId);
+-------------+------------+
| Name | Day |
+-------------+------------+
| Paul Novak | 2009-11-22 |
| Paul Novak | 2009-11-29 |
| Terry Neils | 2009-11-28 |
| Terry Neils | 2009-11-29 |
| Jack Fonda | 2009-12-02 |
| Tom Willis | NULL |
+-------------+------------+
相同的结果,使用更短的 SQL 语句。
RIGHT OUTER JOIN
RIGHT OUTER JOIN 和 RIGHT JOIN 是一样的。 它给出了两个表中匹配的所有记录以及右表的所有可能性。 孤立的右记录在左侧显示 NULL。
mysql> SELECT Name, Day FROM Customers RIGHT JOIN
-> Reservations USING (CustomerId);
+-------------+------------+
| Name | Day |
+-------------+------------+
| Paul Novak | 2009-11-22 |
| Terry Neils | 2009-11-28 |
| Terry Neils | 2009-11-29 |
| Paul Novak | 2009-11-29 |
| Jack Fonda | 2009-12-02 |
+-------------+------------+
这是两个表右连接的输出。 右侧表 (Reservations) 的所有记录在左侧 (Customers) 都有匹配的记录。
MySQL 自然连接
自然连接链接两个表中具有相同名称的所有列。 在我们的 ustomers 和 Reservations 表中,我们有一个名为 CustomerId 的列。
NATURAL INNER JOIN
NATURAL INNER JOIN 自动使用所有匹配的列名进行连接。 在我们的表中,我们在两个表中都有一个名为 CustomerId 的列。
mysql> SELECT Name, Day FROM Customers NATURAL JOIN Reservations; +-------------+------------+ | Name | Day | +-------------+------------+ | Paul Novak | 2009-11-22 | | Terry Neils | 2009-11-28 | | Terry Neils | 2009-11-29 | | Paul Novak | 2009-11-29 | | Jack Fonda | 2009-12-02 | +-------------+------------+
我们得到相同的数据。 SQL 语句不太冗长。
NATURAL LEFT OUTER JOIN
NATURAL LEFT OUTER JOIN 给出了表中所有匹配的记录和左表中的所有其他记录。 它会自动使用所有匹配的列名进行连接。
mysql> SELECT Name, Day FROM Customers
-> NATURAL LEFT JOIN Reservations;
+-------------+------------+
| Name | Day |
+-------------+------------+
| Paul Novak | 2009-11-22 |
| Paul Novak | 2009-11-29 |
| Terry Neils | 2009-11-28 |
| Terry Neils | 2009-11-29 |
| Jack Fonda | 2009-12-02 |
| Tom Willis | NULL |
+-------------+------------+
相同的结果,但使用更少的击键。
NATURAL RIGHT OUTER JOIN
NATURAL RIGHT OUTER JOIN 给出了表中所有匹配的记录和右表中的所有其他记录。 它会自动使用匹配的列名进行连接。
mysql> SELECT Name, Day FROM Customers
-> NATURAL RIGHT JOIN Reservations;
+-------------+------------+
| Name | Day |
+-------------+------------+
| Paul Novak | 2009-11-22 |
| Terry Neils | 2009-11-28 |
| Terry Neils | 2009-11-29 |
| Paul Novak | 2009-11-29 |
| Jack Fonda | 2009-12-02 |
+-------------+------------+
快速回顾
接下来,我们将创建两个小表来回顾我们在这里学到的内容。
mysql> CREATE TABLE AA(A INTEGER); mysql> CREATE TABLE BB(B INTEGER); mysql> INSERT INTO AA VALUES(1); mysql> INSERT INTO AA VALUES(2); mysql> INSERT INTO AA VALUES(3); mysql> INSERT INTO AA VALUES(4); mysql> INSERT INTO BB VALUES(3); mysql> INSERT INTO BB VALUES(4); mysql> INSERT INTO BB VALUES(5); mysql> INSERT INTO BB VALUES(6); mysql> SELECT * FROM AA; +------+ | A | +------+ | 1 | | 2 | | 3 | | 4 | +------+ mysql> SELECT * FROM BB; +------+ | B | +------+ | 3 | | 4 | | 5 | | 6 | +------+
我们已经创建并填充了两个包含数字数据的表。 表 AA 有两个唯一数字 (1, 2),表 BB 也有两个唯一数字 (5, 6)。 它们共享两个数字 (3, 4)。
INNER JOIN
mysql> SELECT * FROM AA JOIN BB ON A = B; +------+------+ | A | B | +------+------+ | 3 | 3 | | 4 | 4 | +------+------+
这是两个表的 INNER JOIN。 我们仅从两个表中获取匹配的值。
LEFT OUTER JOIN
mysql> SELECT * FROM AA LEFT JOIN BB ON A = B; +------+------+ | A | B | +------+------+ | 1 | NULL | | 2 | NULL | | 3 | 3 | | 4 | 4 | +------+------+
这是两个表的 LEFT OUTER JOIN。 我们获得匹配值加上左表中没有匹配记录的值。
RIGHT OUTER JOIN
mysql> SELECT * FROM AA RIGHT JOIN BB ON A = B; +------+------+ | A | B | +------+------+ | 3 | 3 | | 4 | 4 | | NULL | 5 | | NULL | 6 | +------+------+
这是两个表的 RIGHT OUTER JOIN。 我们获得匹配值加上右表中没有匹配记录的值。
在本 MySQL 教程中,我们正在连接表。