Skip to content

第三章|连接、子查询与集合 ​

本章目标 ​

学习如何组合多个表的数据,掌握 JOIN、子查询、EXISTS、UNION 等操作,理解关系数据库的核心能力。

从 INNER JOIN 开始,理解笛卡尔积和连接条件,学会用 LEFT JOIN 处理可选关系,用子查询嵌套查询逻辑,用 EXISTS 检查存在性,用 UNION 合并结果集。

学习路径 ​

按顺序阅读以下文章,每篇包含讲解、示例和练习:

  1. INNER JOIN:内连接与笛卡尔积
    理解表连接的基础,掌握 INNER JOIN 和 ON 条件。

  2. LEFT JOIN 与 RIGHT JOIN:外连接
    处理可选关系,理解 NULL 在外连接中的作用。

  3. 子查询:WHERE、FROM 与 SELECT 中的子查询
    在查询中嵌套查询,理解标量、行、表子查询。

  4. EXISTS 与 IN:存在性检查
    高效检查关联数据是否存在,理解 EXISTS 与 IN 的差异。

  5. UNION 与集合操作:合并结果
    合并多个查询结果,理解 UNION、INTERSECT、EXCEPT。

关键概念 ​

表连接组合多表数据 ​

关系数据库将数据分散在多个表中(范式化),通过 JOIN 重新组合:

sql
-- 用户表
CREATE TABLE users (
    id INT PRIMARY KEY,
    name VARCHAR(50)
);

-- 订单表
CREATE TABLE orders (
    id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10, 2)
);

-- 连接两表
SELECT users.name, orders.amount
FROM users
JOIN orders ON users.id = orders.user_id;

INNER JOIN vs LEFT JOIN ​

  • INNER JOIN:只返回两表都匹配的行
  • LEFT JOIN:返回左表所有行,右表不匹配时为 NULL
sql
-- INNER:只返回有订单的用户
SELECT users.name, COUNT(orders.id) AS order_count
FROM users
INNER JOIN orders ON users.id = orders.user_id
GROUP BY users.name;

-- LEFT:返回所有用户,没有订单的显示 0
SELECT users.name, COUNT(orders.id) AS order_count
FROM users
LEFT JOIN orders ON users.id = orders.user_id
GROUP BY users.name;

子查询提供动态条件 ​

子查询是嵌套在主查询中的查询:

sql
-- 查询高于平均金额的订单
SELECT * FROM orders
WHERE amount > (SELECT AVG(amount) FROM orders);

EXISTS 检查存在性 ​

EXISTS 比 IN 更高效(短路求值):

sql
-- 查询有订单的用户
SELECT * FROM users
WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id);

UNION 合并结果集 ​

UNION 垂直合并多个查询结果:

sql
SELECT name FROM customers
UNION
SELECT name FROM suppliers;

前置知识 ​

  • 掌握 SELECT、WHERE、GROUP BY(第一、二章)
  • 理解主键和外键的概念
  • 能够创建关联表

后续章节 ​

完成本章后,继续学习:

练习答案 ​

本章所有练习的答案和详细解释:第三章练习答案

深入阅读 ​

为什么需要表连接? ​

关系数据库遵循范式化原则,避免数据冗余。用户信息存在 users 表,订单信息存在 orders 表,通过外键关联。JOIN 在查询时重新组合数据,兼顾存储效率和查询灵活性。

笛卡尔积是什么? ​

没有连接条件的 JOIN 会产生笛卡尔积:每个左表行与每个右表行组合。如果 users 有 100 行,orders 有 1000 行,笛卡尔积会产生 100,000 行!ON 条件限制了组合规则。

返回SQL 学习路线 · 开始第一节

用心记录每一步成长