sql子查询是在一条sql语句中嵌套select语句,用于动态提供条件、过滤数据或生成中间结果;按位置分为where(单值)、from(派生表,需别名)和select(相关子查询)三类,并可用in/exists处理多值匹配。

SQL子查询就是在一条SQL语句里嵌套另一条SELECT语句,常用来动态提供条件值、过滤数据或生成中间结果。关键在于外层语句依赖内层查询的结果,且子查询必须加括号。
子查询写在WHERE中:替代固定值
这是最常见用法,用子查询结果作为WHERE的比较值,避免手动查再写死数值。
- 语法格式:WHERE 列名 操作符 (子查询)
- 子查询必须返回单个值(一行一列),否则会报错
- 常用操作符:=、!=、>、
例如:查工资高于平均工资的员工
SELECT name, salary FROM emp WHERE salary > (SELECT AVG(salary) FROM emp);
子查询写在FROM中:当作临时表用
这种叫“派生表(Derived Table)”,子查询结果被当成一张临时表参与连接或筛选,必须起别名。
- 语法格式:FROM (子查询) AS 别名
- 子查询可返回多行多列,但外层需按别名引用字段
- 适合对聚合结果再加工,或简化复杂JOIN逻辑
例如:查各部门平均工资,并只显示高于公司平均的部门
SELECT dept, avg_sal FROM (SELECT dept, AVG(salary) AS avg_sal FROM emp GROUP BY dept) AS t WHERE avg_sal > (SELECT AVG(salary) FROM emp);
子查询写在SELECT中:计算列值
用于为每一行计算一个关联值,要求子查询返回单个值,且通常需关联外层表。
- 语法格式:SELECT 列, (子查询) AS 别名 FROM 表
- 子查询中常通过WHERE与外层表字段关联(相关子查询)
- 性能较弱,每行执行一次子查询,大数据量时慎用
例如:查每个员工姓名及他所在部门的员工总数
SELECT name, (SELECT COUNT(*) FROM emp e2 WHERE e2.dept = e1.dept) AS dept_count FROM emp e1;
IN和EXISTS:处理多值匹配的两种思路
当需要判断某值是否属于一组结果时,IN适合简单列表匹配;EXISTS更强调“是否存在满足条件的记录”,效率常更高,尤其配合索引时。
- IN子查询:右侧必须是单列结果集,不能有NULL(含NULL会导致整行不匹配)
- EXISTS子查询:内部用SELECT 1或SELECT *均可,只要存在匹配行就返回TRUE
- EXISTS天然支持关联,IN一般不关联(除非用相关子查询,但写法绕)
例如:查有员工的部门名称
SELECT dept_name FROM dept WHERE EXISTS (SELECT 1 FROM emp WHERE emp.dept_id = dept.id);









