my+MySQL Atlas数据库学习图谱
官方手册 ↗
LEARN BY QUERYING · MYSQL 8.4

让每一条 SQL
都有清晰的答案。

把多张表连成答案

理解 JOIN、GROUP BY 与 EXISTS,保留你真正需要的数据。

示例数据查询结果动手练习
ONE DATASET, MANY QUESTIONS

准备你的练习数据 4 位客户 · 5 笔订单

+

在自己的空白练习数据库中执行。每项示例都基于初始数据独立验证;事务课程会改变数据,再次练习时请使用新的空白数据库。金额采用 DECIMAL,表使用 InnoDB。

建表与示例数据
CREATE TABLE customers (
  id INT PRIMARY KEY,
  name VARCHAR(40) NOT NULL,
  nickname VARCHAR(40) NULL
) ENGINE=InnoDB;
CREATE TABLE orders (
  id INT PRIMARY KEY,
  customer_id INT NOT NULL,
  amount DECIMAL(10,2) NOT NULL,
  status VARCHAR(20) NOT NULL,
  ordered_at DATE NOT NULL,
  FOREIGN KEY (customer_id) REFERENCES customers(id)
) ENGINE=InnoDB;
INSERT INTO customers VALUES
  (1, 'Ada', 'ada'), (2, 'Linus', NULL),
  (3, 'Grace', 'grace'), (4, 'Guido', NULL);
INSERT INTO orders VALUES
  (1, 1, 120.00, 'paid', '2026-01-02'),
  (2, 1, 80.00, 'paid', '2026-01-05'),
  (3, 2, 200.00, 'pending', '2026-01-06'),
  (4, 2, 50.00, 'paid', '2026-01-07'),
  (5, 3, 150.00, 'paid', '2026-01-09');
下载 dataset.sql ↓
THE PRACTICE

关联与聚合 03

结果基于统一数据集;计划与锁行为需结合实际环境
01MySQL 8.0 · MySQL 8.4

LEFT JOIN 保留没有订单的客户

统计每个客户的已支付金额,同时保留没有订单的 Guido。

常见做法先查客户再逐个查询订单容易产生 N+1 查询。

注意事项

把 o.status 条件放在 WHERE 中会排除空匹配行;一对多 JOIN 会扩大行数,聚合前先确认粒度。

官方依据 ↗核对于 2026-10-06
SQL
SELECT c.name, COALESCE(SUM(o.amount), 0) AS paid_total
FROM customers AS c
LEFT JOIN orders AS o
  ON o.customer_id = c.id AND o.status = 'paid'
GROUP BY c.id, c.name
ORDER BY c.id;

示例结果

namepaid_total
Ada200.00
Linus50.00
Grace150.00
Guido0.00

动手练习

统计每个客户的已支付订单数量,包括 0 笔。

查看参考答案 +

把 SUM(o.amount) 换成 COUNT(o.id),结果依次为 2、1、1、0。

02MySQL 8.0 · MySQL 8.4

WHERE 和 HAVING 分工

按客户汇总所有订单,保留总金额至少 200 元的客户。

常见做法用多个逐行查询再在应用中累计,或者错误地在 WHERE 中使用聚合值。

注意事项

WHERE 过滤输入行,HAVING 过滤分组结果;遵循 ONLY_FULL_GROUP_BY,不随意选择未分组字段。

官方依据 ↗核对于 2026-10-06
SQL
SELECT customer_id, SUM(amount) AS total
FROM orders
GROUP BY customer_id
HAVING SUM(amount) >= 200
ORDER BY customer_id;

示例结果

customer_idtotal
1200.00
2250.00

动手练习

只统计已支付订单,再保留合计至少 150 元的客户。

查看参考答案 +

增加 WHERE status = 'paid' 并修改 HAVING 阈值;客户 1 为 200,客户 3 为 150。

03MySQL 8.0 · MySQL 8.4

用 EXISTS 表达是否存在

只需要知道某个客户有没有已支付订单,不必把所有匹配订单连接出来。

常见做法JOIN 后再 DISTINCT 能得到客户列表,但把存在性问题写成了多行匹配。

注意事项

EXISTS 的作用是表达存在性;实际性能仍要看数据、索引和执行计划。

官方依据 ↗核对于 2026-10-06
SQL
SELECT c.id, c.name
FROM customers AS c
WHERE EXISTS (
  SELECT 1 FROM orders AS o
  WHERE o.customer_id = c.id AND o.status = 'paid'
)
ORDER BY c.id;

示例结果

idname
1Ada
2Linus
3Grace

动手练习

查找完全没有订单的客户。

查看参考答案 +

移除支付状态条件并改成 NOT EXISTS,结果为 Guido。

FROM THE SOURCE

版本与官方更新

自动检查官方发布索引;中文课程由维护者核对更新。