MySQL 入门教程
  • 教程目录
  • 第一章 基础教程
    • 第一节 入门
      • 1.1 安装
      • 1.2 示例数据库
    • 第二节 查询数据
      • 2.1 SELECT 语句
      • 2.2 SELECT DISTINCT 语句
    • 第三节 过滤数据
      • 3.1 WHERE 子句
      • 3.2 AND 运算符
      • 3.3 OR 运算符
      • 3.4 IN 运算符
      • 3.5 BETWEEN 运算符
      • 3.6 LIKE 运算符
      • 3.7 LIMIT 子句
      • 3.8 IS NULL 运算符
    • 第四节 数据排序
      • 4.1 ORDER BY 子句
      • 4.1 自然排序
    • 第五节 连接表
      • 5.1 别名
      • 5.2 INNER JOIN
      • 5.3 LEFT JOIN
      • 5.4 自连接
      • 5.5 CROSS JOIN
    • 第六节 分组数据
      • 6.1 GROUP BY子句
      • 6.2 HAVING 子句
    • 第七节 子查询,派生表和通用表达式
      • 7.1 子查询
      • 7.2 派生表
      • 7.3 公共表表达式
      • 7.4 递归 CTE
    • 第八节 集合操作符
      • 8.1 UNION 和 UNION ALL
      • 8.2 INTERSECT 模拟
    • 第九节 修改数据
      • 9.1 INSERT 语句
      • 9.2 INSERT IGNORE
      • 9.3 UPDATE 语句
      • 9.4 UPDATE JOIN 语句
      • 9.5 DELETE
      • 9.6 ON DELETE CASCADE.
      • 9.7 DELETE JOIN
      • 9.8 REPLACE 语句
      • 9.9 PREPARE 语句
    • 第十节 事务
      • 10.1 事务介绍
      • 10.2 表锁定
    • 第十一节 管理数据库和表
      • 11.1 数据库管理
      • 11.2 MySQL 表类型
      • 11.3 CREATE TABLE
      • 11.4 序列
      • 11.5 ALTER TABLE
      • 11.6 重命名表
      • 11.7 从表中删除列
      • 11.8 向表中添加新列
      • 11.9 删除表
      • 11.10 临时表
      • 11.11 TRUNCATE TABLE
    • 第十二节 索引
      • 12.1 管理索引
      • 12.1 UNIQUE 索引
    • 第十三节 数据类型
      • 13.1 INT
      • 13.2 DECIMAL
      • 13.3 BIT
      • 13.4 BOOLEAN
      • 13.5 CHAR
      • 13.6 VARCHAR
      • 13.7 TEXT
      • 13.8 DATE
      • 13.9 TIME
      • 13.10 DATETIME
      • 13.11 TIMESTAMP
      • 13.12 JSON
      • 13.13 ENUM
    • 第十四节 约束
      • 14.1 NOT NULL 约束
      • 14.2 主键约束
      • 14.2 外键约束
      • 14.4 UNIQUE 约束
      • 14.5 CHECK 约束
    • 第十五节 全球化
      • 15.1 字符集
      • 15.2 校对规则
    • 第十六节 导入和导出
      • 16.1 导入 CSV 文件
      • 16.2 导出为 CSV
  • 第二章 技巧
    • CTE 简介
    • 递归 CTE
    • 邻接列表模型和层次结构
    • 获取行数
    • 比较表
    • 找重复值
    • 删除重复行
    • UUID 和主键
    • 复制表数据
    • 变量
    • 生成列
    • 连续行比较
    • 更改存储引擎
    • 基于正则表达式的搜索
    • row_number 模拟
    • 随机选择记录
    • 选择第 n 个最高纪录
    • 重置自动增量值
    • MariaDB 与 MySQL 比较
    • 间隔
    • NULL 详细和应用
    • 获取今天的日期
    • 将NULL值映射到有意义的值
    • 注释
  • 第三章 存储过程
    • 简介
    • 入门
    • 变量
    • 参数
    • 返回多个值
    • IF语句
    • CASE语句
    • IF和CASE语句的技巧
    • 循环
    • 游标
    • 列出存储过程
    • 错误处理
    • SIGNAL 和 ESIGNAL 语句
    • 存储函数
  • 第四章 触发器
    • 实现
    • 创建
    • 创建多个触发器
    • 管理
    • 计划事件
    • 修改事件
  • 第五章 视图
    • 简介
    • 实现和限制
    • 创建
    • 可更新视图
    • 确保视图一致性
    • 检查选项子句
    • 管理
  • 第六章 全文搜索
    • 简介
    • 定义索引
    • 自然语言全文搜索
    • 布尔全文搜索
    • 查询扩展
    • ngram全文解析器
  • 第七章 函数
  • 第八章 管理
    • 访问控制系统入门
    • 创建用户
    • 授予权限
    • 撤销权限
    • 角色管理
    • 删除用户
    • 维护数据库表
    • 备份数据库
    • 列出数据库
    • 列出表
    • 列出表的列
    • 列出用户
Powered by GitBook
On this page
  • 1. MySQL LEFT JOIN简介
  • 2. MySQL LEFT JOIN示例
  • 3. WHERE子句与ON子句中的条件

Was this helpful?

  1. 第一章 基础教程
  2. 第五节 连接表

5.3 LEFT JOIN

Previous5.2 INNER JOINNext5.4 自连接

Last updated 5 years ago

Was this helpful?

在本教程中,您将了解MySQL LEFT JOIN子句以及如何将其应用于从两个或多个数据库表查询数据。

1. MySQL LEFT JOIN简介

MySQL LEFT JOIN子句允许您从两个或多个数据库表查询数据。LEFT JOIN子句是语句的可选部分,出现在FROM子句之后。

我们假设要从两个表t1和t2查询数据。以下语句说明了连接两个表的LEFT JOIN子句的语法:

SELECT 
    t1.c1, t1.c2, t2.c1, t2.c2
FROM
    t1
        LEFT JOIN
    t2 ON t1.c1 = t2.c1;

当使用LEFT JOIN子句将t1表加入t2表时,如果来自左表t1的行与基于连接条件(t1.c1 = t2.c1)的右表t2匹配,则该行将被包含在结果集中。

如果左表中的行与右表中的行不匹配,则还将选择左表中的行并与右表中的“假”行组合。“假”行对于SELECT子句中的所有相应列都包含NULL值。

换句话说,LEFT JOIN子句允许您从匹配的左右表中查询选择行记录,连接左表(t1)中的所有行,即使在右表(t2)中找不到匹配的行也显示出来,但使用NULL值代替。

下图可帮助您可视化LEFT JOIN子句的工作原理。 两个圆圈之间的交点是两个表中匹配的行,左圆的剩余部分(白色部分)是t1表中不存在t2表中任何匹配行的行。 因此,左表中的所有行都包含在结果集中。

2. MySQL LEFT JOIN示例

2.1 使用MySQL LEFT JOIN子句来连接两个表

在上面的数据库图中:

  • 订单(orders)表中的每个订单必须属于客户(customers)表中的客户。

  • 客户(customers)表中的每个客户在订单(orders)表中可以有零个或多个订单。

要查询每个客户的所有订单,可以使用LEFT JOIN子句,如下所示:

SELECT
 c.customerNumber,
 c.customerName,
 orderNumber,
 o.status
FROM
 customers c
LEFT JOIN orders o ON c.customerNumber = o.customerNumber;

执行上面查询语句,得到以下结果(部分) -

mysql> SELECT
 c.customerNumber,
 c.customerName,
 orderNumber,
 o.status
FROM
 customers c
LEFT JOIN orders o ON c.customerNumber = o.customerNumber;
+----------------+------------------------------------+-------------+------------+
| customerNumber | customerName                       | orderNumber | status     |
+----------------+------------------------------------+-------------+------------+
|            103 | Atelier graphique                  |       10123 | Shipped    |
|            103 | Atelier graphique                  |       10298 | Shipped   |
... 省略部分 ...
|            477 | Mit Vergngen & Co.                 | NULL        | NULL       |
|            480 | Kremlin Collectables, Co.          | NULL        | NULL       |
|            481 | Raanan Stores, Inc                 | NULL        | NULL       |
|            484 | Iberia Gift Imports, Corp.         |       10184 | Shipped    |
|            484 | Iberia Gift Imports, Corp.         |       10303 | Shipped    |
|            486 | Motor Mint Distributors Inc.       |       10109 | Shipped    |
|            486 | Motor Mint Distributors Inc.       |       10236 | Shipped  |
+----------------+------------------------------------+-------------+------------+
350 rows in set

左表是customers表,因此,所有客户都包含在结果集中。 但是,结果集中有一些行具有客户数据,但没有订单数据。如:customerNumber列值为:477,480等。这些行中的订单数据为NULL。也就是说这些客户在orders表中没有任何订单(未购买过任何产品)。

因为我们使用相同的列名(orderNumber)来连接两个表,所以可以使用以下语法使查询更短:

SELECT
 c.customerNumber,
 customerName,
 orderNumber,
 status
FROM
 customers c
LEFT JOIN orders USING (customerNumber);

在上面查询语句中,下面的子句 -

USING (customerNumber)

相当于 -

ON c.customerNumber = o.customerNumber

2.2 使用MySQL LEFT JOIN子句来查找不匹配的行

例如,要查找没有下过订单的所有客户,请使用以下查询:

SELECT 
    c.customerNumber, 
    c.customerName, 
    orderNumber, 
    o.status
FROM
    customers c
        LEFT JOIN
    orders o ON c.customerNumber = o.customerNumber
WHERE
    orderNumber IS NULL;

执行上面查询语句,得到以下结果 -

mysql> SELECT 
    c.customerNumber, 
    c.customerName, 
    orderNumber, 
    o.status
FROM
    customers c
        LEFT JOIN
    orders o ON c.customerNumber = o.customerNumber
WHERE
    orderNumber IS NULL;
+----------------+--------------------------------+-------------+--------+
| customerNumber | customerName                   | orderNumber | status |
+----------------+--------------------------------+-------------+--------+
|            125 | Havel & Zbyszek Co             | NULL        | NULL   |
|            168 | American Souvenirs Inc         | NULL        | NULL   |
|            169 | Porto Imports Co.              | NULL        | NULL   |
|            206 | Asian Shopping Network, Co     | NULL        | NULL   |
|            223 | Natrlich Autos                 | NULL        | NULL   |
|            237 | ANG Resellers                  | NULL        | NULL   |
|            247 | Messner Shopping Network       | NULL        | NULL   |
|            273 | Franken Gifts, Co              | NULL        | NULL   |
|            293 | BG&E Collectables              | NULL        | NULL   |
|            303 | Schuyler Imports               | NULL        | NULL   |
|            307 | Der Hund Imports               | NULL        | NULL   |
|            335 | Cramer Spezialitten, Ltd       | NULL        | NULL   |
|            348 | Asian Treasures, Inc.          | NULL        | NULL   |
|            356 | SAR Distributors, Co           | NULL        | NULL   |
|            361 | Kommission Auto                | NULL        | NULL   |
|            369 | Lisboa Souveniers, Inc         | NULL        | NULL   |
|            376 | Precious Collectables          | NULL        | NULL   |
|            409 | Stuttgart Collectable Exchange | NULL        | NULL   |
|            443 | Feuer Online Stores, Inc       | NULL        | NULL   |
|            459 | Warburg Exchange               | NULL        | NULL   |
|            465 | Anton Designs, Ltd.            | NULL        | NULL   |
|            477 | Mit Vergngen & Co.             | NULL        | NULL   |
|            480 | Kremlin Collectables, Co.      | NULL        | NULL   |
|            481 | Raanan Stores, Inc             | NULL        | NULL   |
+----------------+--------------------------------+-------------+--------+
24 rows in set

3. WHERE子句与ON子句中的条件

请参见以下示例。

SELECT 
    o.orderNumber, 
    customerNumber, 
    productCode
FROM
    orders o
        LEFT JOIN
    orderDetails USING (orderNumber)
WHERE
    orderNumber = 10123;

在本示例中,我们使用LEFT JOIN子句来查询orders表和orderDetails表中的数据。 该查询返回订单号为10123的订单及其购买产品明细信息(如果有的话)。

mysql> SELECT 
    o.orderNumber, 
    customerNumber, 
    productCode
FROM
    orders o
        LEFT JOIN
    orderDetails USING (orderNumber)
WHERE
    orderNumber = 10123;
+-------------+----------------+-------------+
| orderNumber | customerNumber | productCode |
+-------------+----------------+-------------+
|       10123 |            103 | S18_1589    |
|       10123 |            103 | S18_2870    |
|       10123 |            103 | S18_3685    |
|       10123 |            103 | S24_1628    |
+-------------+----------------+-------------+
4 rows in set

但是,如果将条件从WHERE子句移动到ON子句:

SELECT 
    o.orderNumber, 
    customerNumber, 
    productCode
FROM
    orders o
        LEFT JOIN
    orderDetails d ON o.orderNumber = d.orderNumber
        AND o.orderNumber = 10123;

想想上面代码将会输出什么结果 -

mysql> SELECT 
    o.orderNumber, 
    customerNumber, 
    productCode
FROM
    orders o
        LEFT JOIN
    orderDetails d ON o.orderNumber = d.orderNumber
        AND o.orderNumber = 10123;
+-------------+----------------+-------------+
| orderNumber | customerNumber | productCode |
+-------------+----------------+-------------+
|       10123 |            103 | S18_1589    |
|       10123 |            103 | S18_2870    |
|       10123 |            103 | S18_3685    |
|       10123 |            103 | S24_1628    |
|       10298 |            103 | NULL        |
|       10345 |            103 | NULL        |
|       10124 |            112 | NULL        |
.... .... 
|       10179 |            496 | NULL        |
|       10360 |            496 | NULL        |
|       10399 |            496 | NULL        |
+-------------+----------------+-------------+
329 rows in set

在本教程中,我们解释了MySQL LEFT JOIN子句,并向您展示了如何将使用它来从多个数据库表中查询数据。

请注意,如果这些子句在查询中可用,返回的行也必须与和子句中的条件相匹配。

我们来看看在中的两个表:订单表和客户表,两个表的 ER 图如下所示 -

如果使用子句替换LEFT JOIN子句,则只能获得至少有下过一个订单的客户。

当您想要找到右表中与不匹配的左表中的行时,LEFT JOIN子句非常有用。要查询两个表之间的不匹配行,可以向SELECT语句添加一个,以仅查询右表中的列值包含NULL值的行。

请注意,对于子句,ON子句中的条件等同于WHERE子句中的条件。

WHERE
HAVING
示例数据库(yiibaidb)
INNER JOIN
WHERE子句
INNER JOIN
SELECT
img
img