人人都能学编程
English 开始学习
核心 · 数据库第 4 课 / 共 6 课免费阅读

连接表 · SQL 与数据库

怎么把两张表连起来?

课程目录

为什么需要它

订单表里只存了 customer_id = 2,没有存名字 Bo。这是故意的:名字只存在一个地方,改名只需要改一处。想在订单旁边看到名字,就要把表连接回去。JOIN 是 SELECT 之后用得最多的 SQL 技能。

直觉理解

JOIN … ON 把两张表里满足条件的行配成对,通常条件是这张表的 id = 那张表的外键。

  • JOIN(内连接)只保留找到搭档的行。
  • LEFT JOIN 保留左表的每一行;没找到搭档时,右表的列是 NULL。

Eli 从没下过单。内连接会把 Eli 丢掉;左连接会保留 Eli,配上一堆 NULL,这正是找「从没下过单的顾客」的办法。

定义

外键 Foreign key

A column that holds the id of a row in another table, such as orders.customer_id → customers.id.
存放另一张表某行 id 的列,比如 orders.customer_id → customers.id。

表别名

`FROM orders o JOIN customers c` lets you write `o.qty` and `c.name` instead of the full table names.
`FROM orders o JOIN customers c` 让你可以写 `o.qty` 和 `c.name`,不用写完整表名。

示例

谁买了什么

在互动课里运行

三张表,两次连接。每个 ON 说明行怎么配对。

SELECT c.name, p.name AS product, o.qty
FROM orders o
JOIN customers c ON c.id = o.customer_id
JOIN products p ON p.id = o.product_id
WHERE o.day = '2025-03-05';
输出
name | product | qty
Bo | Notebook | 2
Dana | Lamp | 1
逐步执行
  1. L2从订单表开始,简称 o。
  2. L3每笔订单找到它的顾客。
  3. L4……以及它的商品。
  4. L5那天有两笔订单。Bo | Notebook | 2

没下过单的顾客

在互动课里运行

LEFT JOIN 保留了 Eli;Eli 的订单列都是 NULL,WHERE 正是找这个。

SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;
输出
name
Eli
逐步执行
  1. L3每个顾客都留下,不管有没有搭档。
  2. L4只有 Eli 没有匹配的订单。Eli

常见错误

忘了写 ON

没有配对条件的连接会让每一行和每一行配对:7 笔订单 × 5 个顾客 = 35 行没有意义的数据。

列名有歧义

customers 和 products 都有 name 列。要写 c.name 和 p.name,不然数据库不知道你指的是哪个。

小测验

1. 这段代码会输出什么?

SELECT COUNT(*) FROM customers c JOIN orders o ON o.customer_id = c.id;
  1. A
    COUNT(*)
    7
  2. B
    COUNT(*)
    5
  3. C
    COUNT(*)
    8
查看答案

答案:A

7 笔订单每笔都正好找到一个顾客。Eli 没有订单,在内连接里消失了。

2. 这段代码会输出什么?

SELECT COUNT(*) FROM customers c LEFT JOIN orders o ON o.customer_id = c.id;
  1. A
    COUNT(*)
    7
  2. B
    COUNT(*)
    5
  3. C
    COUNT(*)
    8
查看答案

答案:C

7 行配上对的,加上 Eli 那一行(全是 NULL)。

动手练习

3 道练习,分三层:先预测程序的输出,再按新需求改程序,最后从零写一个。代码在浏览器里运行,提交马上判题。

  1. 预测输出每个顾客花了多少

    准确写出查询结果。

  2. 改需求显示名字,不是 id

    这条查询显示 customer_id 和 qty。连接 customers,改成显示顾客的名字和 qty,只要数量不少于 5 的订单。

  3. 从零写从没被大量购买

    返回所有没有任何一笔数量不少于 2 的订单的商品的 name。

在互动课里练这一课

打开互动课,这些例子都能直接改、直接运行,练习题提交马上判题。免费开始,不用注册。

互动课按顺序解锁:前面的课还没学,会先带你到课程地图。

本课术语

术语中文英文定义
Join连接Combining rows of two tables that match on a condition.
Left join左连接A join that keeps every row of the left table, with NULLs where there is no match.
Foreign key外键A column that points to a row in another table by its id.