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”提示










