SQL子查询怎么写?子查询执行流程是怎样的?

来源:IT编程作者:柬埔寨程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《SQL子查询怎么写?子查询执行流程是怎样的?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《SQL子查询怎么写?子查询执行流程是怎样的?》有用,将其分享出去将是对创作者最好的鼓励。

SQL子查询指的是嵌套在SELECT、INSERT、UPDATE、DELETE等SQL语句中的查询语句,它可以作为外层查询的条件、数据源或者计算结果使用,能够帮助我们实现复杂的查询需求,减少多步查询的操作成本。

SQL子查询怎么写?子查询执行流程是怎样的?

SQL子查询的常见类型与写法

1. 标量子查询

标量子查询返回的结果是单个值,通常用在WHERE子句或者SELECT列表中作为计算字段。比如我们需要查询工资高于部门平均工资的员工信息,就可以用标量子查询计算部门平均工资。

-- 查询工资高于所在部门平均工资的员工
SELECT e.emp_id, e.emp_name, e.salary, e.dept_id
FROM employee e
WHERE e.salary > (
    -- 标量子查询,返回当前部门的平均工资
    SELECT AVG(salary)
    FROM employee
    WHERE dept_id = e.dept_id
);

2. 列子查询

列子查询返回的是单列多行的数据集,通常配合IN、ANY、ALL等操作符使用。比如查询所有在销售部或者研发部的员工信息,就可以先通过子查询获取这两个部门的ID。

-- 查询销售部和研发部的员工
SELECT emp_id, emp_name, dept_id
FROM employee
WHERE dept_id IN (
    -- 列子查询,返回销售部和研发部的部门ID
    SELECT dept_id
    FROM department
    WHERE dept_name IN ('销售部', '研发部')
);

3. 表子查询

表子查询返回的是多行多列的数据集,通常作为外层查询的数据源,放在FROM子句后面,需要给子查询起一个别名。比如查询每个部门工资最高的员工,就可以先通过子查询按部门分组获取最高工资,再关联员工表。

-- 查询每个部门工资最高的员工
SELECT e.emp_id, e.emp_name, e.salary, e.dept_id
FROM employee e
INNER JOIN (
    -- 表子查询,获取每个部门的最高工资
    SELECT dept_id, MAX(salary) AS max_salary
    FROM employee
    GROUP BY dept_id
) t ON e.dept_id = t.dept_id AND e.salary = t.max_salary;

4. 相关子查询与不相关子查询

不相关子查询指的是子查询的执行不依赖外层查询的字段,子查询可以独立执行,比如上面的列子查询示例就是典型的不相关子查询。相关子查询则依赖外层查询的字段,子查询不能独立执行,比如第一个标量子查询的示例就是相关子查询,子查询中的dept_id = e.dept_id依赖外层查询的员工表部门ID。

SQL子查询的执行流程解析

1. 不相关子查询的执行流程

不相关子查询的执行逻辑比较简单,数据库会先执行子查询,得到子查询的结果集,再将这个结果集作为外层查询的输入条件或者数据源,执行外层查询。整个过程子查询只会执行一次,执行完成后结果会被缓存,外层查询多次引用子查询结果时不会重复执行子查询。

以之前的列子查询为例,执行步骤为:

  • 第一步:执行子查询SELECT dept_id FROM department WHERE dept_name IN ('销售部', '研发部'),得到部门ID列表,比如(1, 3)。
  • 第二步:将外层查询的dept_id与子查询返回的ID列表做匹配,筛选出符合条件的员工记录。

2. 相关子查询的执行流程

相关子查询的执行逻辑和不相关子查询不同,由于子查询依赖外层查询的字段,所以子查询不能独立执行。数据库会先遍历外层查询的每一条记录,将当前记录的对应字段值传递给子查询,执行子查询得到结果,再判断外层查询的当前记录是否符合条件,符合则保留,不符合则丢弃,然后处理下一条外层记录,重复这个过程直到外层所有记录处理完成。

以标量子查询查询高于部门平均工资的员工为例,执行步骤为:

  • 第一步:从员工表中取出第一条员工记录,获取该员工的dept_id值,比如是2。
  • 第二步:执行子查询SELECT AVG(salary) FROM employee WHERE dept_id = 2,得到部门2的平均工资。
  • 第三步:比较当前员工的工资和子查询返回的平均工资,如果员工工资更高,则保留该员工记录,否则丢弃。
  • 第四步:处理员工表的下一条记录,重复上面的步骤,直到所有员工记录处理完成。

3. 子查询的优化执行逻辑

现代数据库优化器会对子查询做很多优化,比如将子查询转换为连接查询,减少相关子查询的重复执行次数。比如上面的相关子查询示例,优化器可能会将其重写为表连接的形式,一次性获取所有部门的平均工资,再和员工表做匹配,避免对每条员工记录都执行一次子查询,提升查询性能。

如果子查询的结果集很小,优化器也可能选择先执行子查询,将结果缓存,再执行外层查询,和不相关子查询的执行逻辑类似。我们可以通过EXPLAIN命令查看数据库对子查询的执行计划,了解子查询的实际执行方式,针对性做优化。

-- 查看子查询的执行计划
EXPLAIN
SELECT e.emp_id, e.emp_name, e.salary, e.dept_id
FROM employee e
WHERE e.salary > (
    SELECT AVG(salary)
    FROM employee
    WHERE dept_id = e.dept_id
);

子查询编写注意事项

编写子查询时需要注意几个问题,避免写出性能问题或者逻辑错误的语句。首先,相关子查询如果外层表数据量很大,子查询又比较复杂,会导致查询性能非常差,这种场景下尽量考虑重写为连接查询。其次,子查询作为数据源放在FROM子句后面时,必须给子查询起别名,否则数据库会报错。另外,子查询返回的结果类型需要和外层查询的使用场景匹配,比如标量子查询用在比较场景中时,必须保证子查询最多返回一条记录,否则会报单行子查询返回多行的错误。

SQL子查询执行流程查询优化修改时间:2026-07-15 18:48:27

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。