在 MySQL 中,子查询(Subquery)是指嵌套在另一个 SQL 查询中的查询语句。它可以出现在 SELECT、FROM、WHERE 或 HAVING 子句中,用来动态生成条件或数据源。掌握子查询能让你更灵活地处理复杂的数据检索需求。
什么是子查询?
子查询就是一个 SELECT 语句,作为另一个查询的一部分运行。外层的查询称为“主查询”,内部的 SELECT 语句就是“子查询”。子查询通常用括号包裹。
示例:
SELECT name FROM users WHERE age > (SELECT AVG(age) FROM users);
这条语句的意思是:找出所有年龄大于平均年龄的用户。其中
(SELECT AVG(age) FROM users)就是子查询。
子查询的常见使用场景
1. 在 WHERE 子句中使用子查询
这是最常见的用法,用于根据另一个查询的结果来过滤数据。
SELECT * FROM orders WHERE user_id IN (SELECT id FROM users WHERE city = '北京');
查找所有来自“北京”的用户的订单。
注意:IN、NOT IN、=、!=、>、
2. 在 FROM 子句中使用子查询(派生表)
子查询可以作为临时表出现在 FROM 后面,也叫“派生表”或“内联视图”。
SELECT AVG(order_total) FROM (
SELECT user_id, SUM(amount) AS order_total
FROM orders
GROUP BY user_id
) AS user_totals;计算每个用户的订单总额,再求这些总额的平均值。
注意:必须给子查询起一个别名(如 AS user_totals),否则会报错。
3. 在 SELECT 子句中使用标量子查询
子查询返回单个值时,可以在 SELECT 中使用。
SELECT
id,
name,
(SELECT COUNT(*) FROM orders WHERE orders.user_id = users.id) AS order_count
FROM users;查询每个用户的信息,并显示其订单数量。
要求:这种子查询必须返回一行一列(即一个值),否则会出错。
子查询的类型
标量子查询:返回单个值,常用于 SELECT 或 WHERE 中。 行子查询:返回一行多列,可用于比较行数据。 列子查询:返回一列多行,常与 IN、ANY、ALL 配合使用。 表子查询:返回多行多列,通常用在 FROM 中。例子:使用 ANY 和 ALL
-- 找出工资高于任意一名销售员的员工 SELECT name, salary FROM employees WHERE salary > ANY (SELECT salary FROM employees WHERE job = 'sales'); <p>-- 找出工资高于所有销售员的员工 SELECT name, salary FROM employees WHERE salary > ALL (SELECT salary FROM employees WHERE job = 'sales');
相关子查询 vs 非相关子查询
非相关子查询:子查询可以独立运行,不依赖外部查询。
SELECT * FROM users WHERE age > (SELECT AVG(age) FROM users);
相关子查询:子查询依赖于外部查询的字段,每次主查询处理一行时,子查询都会重新执行。
SELECT u.name, u.age FROM users u WHERE u.age > (SELECT AVG(age) FROM users WHERE city = u.city);
这个查询找出每个城市中年龄高于该城市平均年龄的用户。子查询中的
u.city来自主查询,因此是相关子查询。
注意事项和性能建议
子查询不能直接在 DML 语句(如 UPDATE、DELETE)中引用目标表,会报错 “You can't specify target table for update in FROM clause”。 深层嵌套的子查询可能影响性能,建议在大数据量时考虑使用 JOIN 替代。 使用索引可以显著提升子查询效率,尤其是 WHERE 或 IN 中涉及的字段。 某些情况下,JOIN 比子查询更高效,特别是表连接逻辑清晰时。基本上就这些。子查询是 MySQL 中非常实用的功能,合理使用可以让查询逻辑更清晰。刚开始可以从小例子入手,逐步尝试复杂嵌套。只要注意语法结构和返回结果的匹配,就能避免大多数错误。
