# 在 MySQL 中连接表

> 原文： [http://zetcode.com/databases/mysqltutorial/joins/](http://zetcode.com/databases/mysqltutorial/joins/)

在 MySQL 教程的这一部分中，我们将连接 MySQL 中的表。

关系数据库的真正力量和收益来自于连接表。 SQL `JOIN`子句合并数据库中两个或多个表中的记录。 基本上有两种连接类型：`INNER`和`OUTER`。

在本教程的这一部分中，我们将使用`Customers`和`Reservations`表。

```sql
mysql> SELECT * FROM Customers;
+------------+-------------+
| CustomerId | Name        |
+------------+-------------+
|          1 | Paul Novak  |
|          2 | Terry Neils |
|          3 | Jack Fonda  |
|          4 | Tom Willis  |
+------------+-------------+

```

这些是`Customers`表中的值。

```sql
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) syntax`。 如果名称不同，则说我们有`CustomerId`和`CId`，我们将使用`ON Customers.CustomerId = Reservations.CId`语法。

## 内连接

内连接是最常见的连接类型。 这也是默认的连接。 内连接仅从数据库表中选择具有匹配值的记录。 我们有内连接的三种类型：`INNER JOIN`，`NATURAL INNER JOIN`和`CROSS INNER JOIN`。 `INNER`关键字可以省略。

### 内连接

```sql
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`关键字。

该语句等效于以下语句：

```sql
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`将一个表中的所有记录与另一表中的所有记录组合在一起。 这种连接几乎没有实用价值。 它也称为记录的笛卡尔积。

```sql
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 语句可以达到相同的结果：

```sql
SELECT Name, Day FROM Customers, Reservations;

```

## 外连接

外连接不需要两个连接表中的每个记录都具有匹配的记录。 外连接有三种类型。 左外连接，右外连接和全外连接。 在创建教程时，MySQL 不支持全外连接。

如前所述，内连接是最常见的连接。 外连接对于查找孤立记录可能很有用。 如果一个人没有预订，是顾客吗？ 如果我们无法与客户匹配，预订是否有效？

### 左外连接

即使与右表不匹配，`LEFT OUTER JOIN`也将从左表返回所有值。 在这样的行中，将有`NULL`值。 换句话说，左外连接返回左表中的所有值，以及右表中的匹配值。 注意，可以省略`OUTER`关键字。

```sql
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 语句将不再那么冗长。

```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 JOIN`相同。 它提供了两个表中所有记录的匹配以及正确表的所有可能性。 右侧孤立记录在左侧显示`NULL`。

```sql
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 |
+-------------+------------+

```

这是两个表的正确连接的输出。 右侧表的所有记录（预订）在左侧均具有匹配的记录（客户）。

## 自然连接

自然连接将两个具有相同名称的表中的所有列链接在一​​起。 在`ustomers`和`Reservations`表中，有一个名为`CustomerId`的列。

### 自然内连接

`NATURAL INNER JOIN`自动使用所有匹配的列名进行连接。 在我们的表中，两个表中都有一个名为`CustomerId`的列。

```sql
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`提供表中所有匹配的记录以及左表中的所有其他记录。 它会自动使用所有匹配的列名进行连接。

```sql
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`提供表中的所有匹配记录以及右表中的所有其他记录。 它会自动使用匹配的列名进行连接。

```sql
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 |
+-------------+------------+

```

## 快速回顾

接下来，我们将创建两个小表来回顾我们在这里学到的东西。

```sql
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）。

### 内连接

```sql
mysql> SELECT * FROM AA JOIN BB ON A = B;
+------+------+
| A    | B    |
+------+------+
|    3 |    3 |
|    4 |    4 |
+------+------+

```

这是两个表上的`INNER JOIN`。 我们仅从两个表中获得匹配的值。

### 左外连接

```sql
mysql> SELECT * FROM AA LEFT JOIN BB ON A = B;
+------+------+
| A    | B    |
+------+------+
|    1 | NULL |
|    2 | NULL |
|    3 |    3 |
|    4 |    4 |
+------+------+

```

这是两个表上的`LEFT OUTER JOIN`。 我们获得匹配的值以及左表中没有数学记录的值。

### 右外连接

```sql
mysql> SELECT * FROM AA RIGHT JOIN BB ON A = B;
+------+------+
| A    | B    |
+------+------+
|    3 |    3 |
|    4 |    4 |
| NULL |    5 |
| NULL |    6 |
+------+------+

```

这是两个表上的`RIGHT OUTER JOIN`。 我们得到匹配的值，再加上右表中没有匹配记录的值。

在 MySQL 教程的这一部分中，我们将连接表。