SQL语法进阶篇(一),数据库复杂查询——子查询
以下是关于 SQL 进阶语法与复杂查询 的详细解析,涵盖 子查询、窗口函数、递归查询 的核心语法、应用场景与实战案例,帮助突破 SQL 高级技能瓶颈。
一、子查询(Subquery)
1. 定义
子查询是嵌套在主查询的WHERE
、HAVING
、SELECT
、FROM
等子句中。它的执行逻辑是先执行子查询,得到一个结果集,然后将这个结果集用于主查询的进一步处理。
2. 分类
为了更清晰地展示不同查询的运用,下面使用 Kooboo 在线工具中的 DrawDB 数据库设计 展示具体的表结构和示例数据(数据表的sql文件于文章顶部):
-
标量子查询:返回单个值(一行一列)- 概念:返回单一值(一行一列)的子查询。该值可以作为一个普通的标量值参与主查询的运算或比较。
- 使用场景:常用于在主查询中根据某个特定条件获取一个单一值
- 示例:
-- 查询 HR 部门的所有员工 SELECT employee_name FROM employees WHERE department_id = ( SELECT department_id FROM departments WHERE department_name = 'HR' ); -- 子查询SELECT department_id ~ 'HR'返回HR部门的department_id -- 主查询根据这个单一值筛选出属于该部门的员工。
-
行子查询:返回一行(多列)
- 概念:返回一行多列数据的子查询,主查询可以使用行比较运算符(如
=
、<>
等)来比较行子查询的结果。 - 使用场景:当需要同时比较多个列的值时使用。例如,
- 示例:
-- 找出与某个特定员工在多个属性上都相同的其他员工 SELECT * FROM employees WHERE (department_id, salary) = ( SELECT department_id, salary FROM employees WHERE employee_name = 'Alice' ); -- 子查询返回Alice员工的department_id和salary组成的行 -- 主查询找出具有相同department_id和salary的其他员工
- 概念:返回一行多列数据的子查询,主查询可以使用行比较运算符(如
-
列子查询:返回一列(多行)
- 概念:返回一列多行数据的子查询。主查询通常会使用
IN
、ANY
、ALL
等操作符与列子查询的结果进行比较。 - 使用场景:当需要在主查询中筛选出符合多个值条件的记录时使用。
- 示例:
-- 要找出工资高于某个部门部分员工工资的员工 SELECT employee_name FROM employees WHERE salary > ANY ( SELECT salary FROM employees WHERE department_id = ( SELECT department_id FROM departments WHERE department_name = 'HR' ) ); -- 子查询返回HR部门所有员工的工资列,主查询筛选出工资高于该列中任意一个值的员工。 -- ANY:满足条件的任意一个
- 概念:返回一列多行数据的子查询。主查询通常会使用
-
表子查询:返回多行多列(作为临时表)
- 概念:返回多行多列数据的子查询,相当于一个临时表。主查询可以将表子查询的结果当作一个普通表来使用。
- 使用场景:当需要对一个复杂查询的结果进行进一步处理时使用。
- 示例:
-- 对一个分组统计的结果再进行筛选 SELECT * FROM ( SELECT department_id, AVG(salary) AS avg_salary FROM employees GROUP BY department_id ) AS dept_avg_salary WHERE avg_salary > 5000; -- GROUP BY:当数据进行分组
- 必须用
GROUP BY
的情况:当需要按某列 / 多列将数据分组,对每个组分别进行聚合统计(如 “每个部门”“每个类别” 的汇总)。 - 无需用
GROUP BY
的情况:当需要对全表数据进行单一的聚合统计(如 “所有数据的总和 / 平均值”)。
- 必须用
- 掌握 SQL复杂子查询后→下一篇学习 复杂窗口函数查询