MySQL 的子查询(Subquery)是嵌套在其他 SQL 语句中的查询,也称为内部查询,而包含子查询的语句称为外部查询。子查询可以让 SQL 语句更灵活,用于过滤、计算或生成临时数据。
子查询通常放在在 SELECT、INSERT、UPDATE、DELETE 等语句中,用括号 () 包裹:
外部查询 (SELECT 列 FROM 表 WHERE 条件);
子查询返回单个值或一组值,用于 WHERE 条件判断。
示例 1:返回单个值(单行子查询)
SELECT name, department
FROM employees
WHERE department = (
SELECT department FROM employees WHERE id = 1
);
示例 2:返回多个值(多行子查询)
使用 IN、ANY、ALL 等关键字:
SELECT * FROM orders
WHERE employee_id IN (
SELECT id FROM employees WHERE department IN ('销售部', '市场部')
);
子查询返回单个值,作为主查询结果集中的一列。
SELECT
id,
name,
(SELECT COUNT(*) FROM orders WHERE user_id = users.id) AS order_count
FROM users;
子查询返回结果集,作为主查询的数据源(需给子查询起别名)。
SELECT
dept_avg.department,
dept_avg.avg_salary,
dept_count.emp_count
FROM
(SELECT department, AVG(salary) AS avg_salary FROM employees GROUP BY department) AS dept_avg
JOIN
(SELECT department, COUNT(*) AS emp_count FROM employees GROUP BY department) AS dept_count
ON dept_avg.department = dept_count.department;
SELECT department, COUNT(*) AS emp_count
FROM employees
GROUP BY department
HAVING COUNT(*) > (
SELECT AVG(emp_count)
FROM (SELECT COUNT(*) AS emp_count FROM employees GROUP BY department) AS dept_counts
);
子查询中引用了外部查询的列,每行数据单独执行一次子查询。
SELECT name, department, salary
FROM employees e1
WHERE salary > (
SELECT AVG(salary)
FROM employees e2
WHERE e1.department = e2.department
);
-
性能问题:复杂的子查询(尤其是关联子查询)可能导致性能下降,可考虑用
JOIN 替代。
-
返回值限制:
-
若子查询用在
=、> 等比较符后,必须返回单个值(单行单列)。
-
若用
IN,子查询可返回多行单列。
-
可读性:嵌套过深的子查询(如 3 层以上)建议拆分或用 CTE(公用表表达式)优化。
-
关键字支持:部分子查询中不能使用
LIMIT、FOR UPDATE 等关键字。
多数情况下,子查询和 JOIN 可以实现相同功能,但:
-
子查询更直观,适合简单逻辑。
-
JOIN 通常性能更好,适合复杂关联查询。
例如,前文的部门用户查询可用 JOIN 改写:
SELECT e1.name, e1.department
FROM employees e1
JOIN employees e2 ON e1.department = e2.department
WHERE e2.id = 1 AND e1.id != 1;
根据实际场景选择合适的方式,优先保证可读性和性能。