MySQL 子查询是在 SQL 语句中嵌套 SELECT 语句,可置于 WHERE、SELECT、FROM、HAVING 等子句中,需加圆括号;分相关(依赖外部字段)与非相关(独立执行)两类,返回单值、单列或多行决定操作符使用。

MySQL 子查询就是在一条 SQL 语句中嵌套另一个 SELECT 语句,常用于替代 JOIN、动态筛选或计算中间结果。掌握基础用法能显著提升查询灵活性和可读性。
子查询的基本写法与位置
子查询必须用圆括号包裹,可出现在 SELECT、FROM、WHERE、HAVING 等子句中,但不同位置有不同限制:
- WHERE 子句中 :最常见,用于条件过滤,如 WHERE age > (SELECT AVG(age) FROM users)
- SELECT 子句中 :只能返回单个值(标量子查询),常用于计算列,如 SELECT name, (SELECT COUNT(*) FROM orders WHERE user_id = u.id) AS order_count FROM users u
- FROM 子句中 :称为派生表(derived table),必须指定别名,如 SELECT * FROM (SELECT user_id, COUNT(*) c FROM orders GROUP BY user_id) t WHERE t.c > 5
- HAVING 子句中 :用于分组后条件,如 HAVING SUM(price) > (SELECT AVG(total) FROM monthly_sales)
相关子查询 vs 非相关子查询
区分关键在于子查询是否依赖外部查询的字段:
- 非相关子查询 :独立执行一次,结果被主查询复用,效率高,例如 WHERE salary > (SELECT MAX(salary) FROM managers)
- 相关子查询 :每次主查询行变化时都重新执行,性能较低但逻辑灵活,例如 WHERE salary > (SELECT AVG(salary) FROM employees e2 WHERE e2.dept_id = e1.dept_id)(每部门单独算平均)
常用操作符与注意事项
子查询返回结果类型决定可用的操作符:
- 返回单值 → 可用 =、>、=、等比较运算符
- 返回多行单列 → 必须配合 IN、ANY、ALL,如 WHERE id IN (SELECT user_id FROM active_logs)
- 返回多行多列 → 只能在 FROM 中作为派生表使用
- 注意 NULL 处理:NOT IN 遇到子查询含 NULL 会整体返回空结果,建议改用 NOT EXISTS
简单优化建议
子查询易写但不当使用会影响性能:
- 优先考虑用 JOIN 替代 WHERE 中的相关子查询,尤其数据量大时
- 确保子查询中涉及的字段有索引(特别是 WHERE 和 JOIN 条件字段)
- 避免在 SELECT 列表中使用多次相同子查询,可改用 LEFT JOIN 或 CTE(MySQL 8.0+)
- 用 EXPLAIN 分析执行计划,确认是否出现“DEPENDENT SUBQUERY”提示