1. 子查询的本质与分类
SQL子查询本质上就是一个嵌套在另一个SQL语句中的完整查询块。它就像俄罗斯套娃一样,外层查询依赖内层查询的结果作为输入条件或数据源。根据子查询返回结果的不同,我们可以将其分为以下几类:
-
标量子查询:返回单一值的子查询,通常用在WHERE或SELECT子句中作为比较条件。例如查询工资高于平均工资的员工:
sql复制SELECT name FROM employees WHERE salary > (SELECT AVG(salary) FROM employees); -
列子查询:返回单列多行的结果集,常用于IN或ANY/ALL运算符的条件判断。例如查询所有销售部门的员工:
sql复制SELECT name FROM employees WHERE dept_id IN (SELECT id FROM departments WHERE name = 'Sales'); -
行子查询:返回单行多列的结果,通常与行构造函数一起使用。例如查询与特定员工工资和职位都相同的其他员工:
sql复制SELECT name FROM employees WHERE (salary, position) = (SELECT salary, position FROM employees WHERE id = 1001); -
表子查询:返回多行多列的完整结果集,通常作为派生表使用。例如查询各部门工资最高的员工:
sql复制SELECT d.name, e.name, e.salary FROM departments d JOIN (SELECT dept_id, name, salary, RANK() OVER(PARTITION BY dept_id ORDER BY salary DESC) as rnk FROM employees) e ON d.id = e.dept_id AND e.rnk = 1;
提示:MySQL 5.7及以下版本对子查询的优化能力较弱,复杂子查询建议拆分为JOIN操作。8.0版本后优化器对子查询的处理能力大幅提升。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 子查询的执行原理与优化
2.1 子查询的执行过程
MySQL处理子查询时通常采用以下两种策略:
-
物化(Materialization):优化器先将子查询结果计算出来并存储在临时表中,然后外层查询再使用这个临时表。这种方式适合子查询结果集较小且被多次引用的情况。
-
半连接(Semi-join):将子查询转换为JOIN操作,通过去重保证语义正确。8.0版本新增的优化策略,特别适合IN和EXISTS子查询。
查看执行计划可以了解优化器选择的具体策略:
sql复制EXPLAIN SELECT * FROM orders
WHERE customer_id IN (SELECT id FROM customers WHERE vip = 1);
2.2 性能优化要点
-
索引利用:确保子查询中WHERE条件的列有适当索引。例如:
sql复制-- 确保customers表的vip列有索引 SELECT * FROM orders WHERE customer_id IN (SELECT id FROM customers WHERE vip = 1); -
LIMIT应用:在子查询中使用LIMIT减少处理
