嵌套查询(Subquery / Nested Query,也叫子查询)在 SQL 里非常常见,但写的时候容易踩坑。下面从语法规则、常见错误、性能与书写建议几个角度总结要注意的点。
() 包起来SELECT *
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
❌ 忘记括号会直接报错。
常见位置:
WHERE 子句FROM 子句(派生表)SELECT 子句(标量子查询)HAVING 子句SELECT t.avg_sal
FROM (SELECT AVG(salary) AS avg_sal FROM employees) t;
❌ 不起别名在标准 SQL 中是不允许的。
| 使用场景 | 运算符 | 子查询返回 |
|---|---|---|
| 单行 | = > < >= |
只能一行一列 |
| 多行 | IN ANY ALL |
多行一列 |
❌ 错误示例:
SELECT *
FROM emp
WHERE deptno = (SELECT deptno FROM dept);
如果子查询返回多行,会报:
single-row subquery returns more than one row
✅ 正确:
WHERE deptno IN (SELECT deptno FROM dept);
SELECT name,
(SELECT MAX(salary) FROM employees) AS max_sal
FROM departments;
❌ 不能返回多行或多列。
NOT IN + NULL = 永远无结果WHERE id NOT IN (SELECT manager_id FROM emp);
如果 manager_id 中有 NULL,结果可能是空集。
✅ 更安全写法:
WHERE id NOT IN (
SELECT manager_id FROM emp WHERE manager_id IS NOT NULL
);
或用 NOT EXISTS。
子查询依赖外层查询:
SELECT e.name
FROM emp e
WHERE salary > (
SELECT AVG(salary)
FROM emp
WHERE deptno = e.deptno
);
⚠️ 注意:
JOIN 或窗口函数优化-- 不推荐
SELECT *
FROM emp
WHERE deptno IN (SELECT deptno FROM dept WHERE loc='NY');
-- 推荐
SELECT e.*
FROM emp e
JOIN dept d ON e.deptno = d.deptno
WHERE d.loc = 'NY';
超过 3 层嵌套,建议:
WITH)WITH avg_sal AS (
SELECT deptno, AVG(salary) s
FROM emp
GROUP BY deptno
)
SELECT *
FROM emp e
JOIN avg_sal a ON e.deptno = a.deptno
WHERE e.salary > a.s;
FROM 子查询索引优化括号不能少、返回行数要匹配、NULL 要小心、相关子查询慎用、能用 JOIN/CTE 就别嵌套太深。
如果你有具体数据库(MySQL / Oracle / PG)或具体 SQL 报错,我可以帮你逐句改。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。