平时做技术实践时,很多问题不是概念不会,而是细节没串起来。拿“Mysql数据库中的子查询、标量子查询、行子查询、列子查询及表子查询实例……”来说,它看着像小点,放到项目里常会牵出环境、配置、兼容性和维护成本。下面按实际采用顺序,把思路、关键写法和容易踩坑的地方讲清楚,便于大家直接对照操作。
一、什么是子查询?
理解这一步时,子查询(Subquery)是指嵌套在另一条 SQL 语句中的 SELECT 语句,也叫内层查询。外层包含它的语句叫主查询或外层查询。根据子查询得到结果的"形状",能够分为四种类型:

子查询 = 一条 SELECT 嵌套在另一条 SELECT 内部
- 外面的查询叫 主查询 / 外层查询
- 里面嵌套的查询叫 子查询 / 内层查询
执行顺序:先执行子查询 → 得到结果 → 再把结果交给主查询采用
基本结构:
SELECT 字段列表
FROM 表名
WHERE 字段 运算符 (
SELECT 字段
FROM 表名
WHERE 条件
);
二、子查询按结果集分类(最重要)
子查询一共分 4 类,你必须全部掌握:
1. 标量子查询(单行单列)
标量子查询:
子查询得到的结果是一个单个值(数字,字符串,日期等),最轻松的形式,这种子查询称为 标量子查询。
得到:一个值能用符号:= > < >= <= !=
示例:查询 “研发部” 的所有员工
SELECT emp.*
FROM emp
WHERE emp.dept_id = (
SELECT dept.id
FROM dept
WHERE dept.name = '研发部'
);
扩展:
ANY:满足任意一个ALL:满足全部
得到单个值在这个场景下,(1行1列),能够用在任何需单值的地方,比如 =、>、< 等比较运算符后面。
示例:查询工资高于平均工资的员工
SELECT name, salary
FROM employees
WHERE salary > (
SELECT AVG(salary)
FROM employees
);
内层的 SELECT AVG(salary) 只得到一个数字,外层用 > 直接比较。如果子查询得到多行,MySQL 会报错。
2.列子查询(Column Subquery)
得到多行一列,常配合 IN、NOT IN、ANY、ALL 采用。
示例 1:IN — 查询属于某些部门的员工
SELECT name
FROM employees
WHERE dept_id IN (
SELECT id
FROM departments
WHERE location = '上海'
);
示例 2:ANY — 工资比研发部任意一人高即可
SELECT name
FROM employees
WHERE salary > ANY (
SELECT salary FROM employees WHERE dept_id = 3
);
示例 3:ALL — 工资比研发部所有人都高
SELECT name
FROM employees
WHERE salary > ALL (
SELECT salary FROM employees WHERE dept_id = 3
);
ANY 相当于"至少一个满足",ALL 相当于"全部都满足"。
-- 查询销售部和市场部的所有员工的信息
select id from dept where name='销售部' or name='市场部'; -- 返回值(2,4)
select * from emp33 where id in(2,4)
等价于
select* from emp33 where id in (select id from dept where name='销售部' or name='市场部');
3. 行子查询(单行多列)
得到:一行多个字段示例:查询和 “张三” 同部门、同职位的员工
SELECT emp.*
FROM emp
WHERE (emp.dept_id, emp.job) = (
SELECT emp.dept_id, emp.job
FROM emp
WHERE emp.name = '张三'
);
得到一行多列,需用行构造器 (col1, col2, ...) 来匹配。
示例:查询与某员工薪资和职位都相同的其他员工
SELECT name
FROM employees
WHERE (salary, job_id) = (
SELECT salary, job_id
FROM employees
WHERE name = '张三'
);
括号里的 (salary, job_id) 和子查询得到的 (salary, job_id) 一一对应进行比较。兼容的操作符有 =、<>、<、> 等。
select * from emp33 where (salary,managerid) =(select salary,managerid from emp33 where name='张无忌');
等价于
select * from emp33 where managerid=(select managerid from emp33 where name='张无忌') and salary=(select salary from emp33 where name='张无忌');
4. 表子查询(多行多列)
子查询放在 FROM 后面,当作一张临时表采用,必须起别名。
示例:查询每个部门的平均薪资
sql
SELECT temp.dept_id, temp.avg_sal
FROM (
SELECT emp.dept_id, AVG(emp.salary) AS avg_sal
FROM emp
GROUP BY emp.dept_id
) AS temp;
三、子查询出现的 3 个位置(高频考点)
子查询不只能出现在 WHERE 里,还能够出现在不同的位置:
| 位置 | 常用类型 | 说明 |
|---|---|---|
WHERE / HAVING | 标量、行、列 | 作为条件值 |
FROM | 表子查询 | 作为派生表,必须起别名 |
SELECT 后 | 标量 | 作为查询字段值(关联子查询) |
1. 放在 WHERE 后(最常用,标量、行、列)
SELECT emp.name
FROM emp
WHERE emp.dept_id = (
SELECT dept.id
FROM dept
WHERE dept.name = '财务部'
);
2. 放在 FROM 后(当作表,表子查询)
SELECT temp.name
FROM (
SELECT emp.name
FROM emp
WHERE emp.salary > 10000
) AS temp;
3. 放在 SELECT 后(相关子查询,标量)
SELECT
emp.name,
(
SELECT dept.name
FROM dept
WHERE dept.id = emp.dept_id
) AS dept_name
FROM emp;
四、子查询关键字详解(IN / ANY / ALL / EXISTS)
1. IN
子查询得到多个值时用
SELECT emp.*
FROM emp
WHERE emp.dept_id IN (
SELECT dept.id
FROM dept
);
2. ANY
满足子查询任意一个条件即可
SELECT emp.*
FROM emp
WHERE emp.salary > ANY (
SELECT emp.salary
FROM emp
WHERE emp.dept_id = 1
);
3. ALL
必须满足子查询所有条件
SELECT emp.*
FROM emp
WHERE emp.salary > ALL (
SELECT emp.salary
FROM emp
WHERE emp.dept_id = 2
);
4. EXISTS
判断子查询是否有结果,有则为真
SELECT emp.*
FROM emp
WHERE EXISTS (
SELECT *
FROM dept
WHERE dept.id = emp.dept_id
);
五、子查询 VS 多表连接(对比)
- 子查询:逻辑清晰,适合分步查询
- 多表连接:效率更高,适合大数据量
示例(效果一样):
-- 子查询写法
SELECT emp.name
FROM emp
WHERE emp.dept_id = (
SELECT dept.id
FROM dept
WHERE dept.name = '研发部'
);
-- 多表连接写法
SELECT emp.name
FROM emp
INNER JOIN dept
ON emp.dept_id = dept.id
WHERE dept.name = '研发部';
六、子查询必须遵守的规则(考试必背)
- 子查询必须放在 括号内
- 标量子查询只能得到 一个值
- 列子查询得到 一列
- FROM 后的子查询 必须起别名
- 子查询先执行,主查询后执行
- 子查询中不能采用 order by(除非搭配 limit)
七、综合实战案例(最经典)
案例 1:查询工资最高的员工
SELECT emp.*
FROM emp
WHERE emp.salary = (
SELECT MAX(emp.salary)
FROM emp
);
案例 2:查询每个部门工资最高的员工
SELECT emp.*
FROM emp
INNER JOIN (
SELECT emp.dept_id, MAX(emp.salary) AS max_sal
FROM emp
GROUP BY emp.dept_id
) AS temp
ON emp.dept_id = temp.dept_id
AND emp.salary = temp.max_sal;
案例 3:查询没有员工的部门
SELECT dept.*
FROM dept
WHERE dept.id NOT IN (
SELECT DISTINCT emp.dept_id
FROM emp
WHERE emp.dept_id IS NOT NULL
);

理解子查询的关键在于:先看内层查询得到什么形状的数据,再根据形状选择合适的操作符和位置
总结
到此这篇关于Mysql数据库中子查询、标量子查询、行子查询、列子查询及表子查询的文章就介绍到这了,更多相关Mysql子查询内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多兼容脚本之家!
- MySQL里面的子查询实例
- 详细讲述MySQL中的子查询操作
- Mysql子查询IN中采用LIMIT应用示例
- MySQL笔记之子查询采用介绍
- MySQL子查询的几种常用形式介绍
- 浅谈MySQL中的子查询优化技巧
- mysql数据库SQL子查询(史上最详细)
- 一文了解MySQL的四大子查询
- MySQL子查询操作实例详解

