MySQL支持对语句的嵌套,我们可以在
SELECT
语句中嵌套
SELECT
语句,从而形成结构化、语句间独立化、清晰化,更加强大的查询语句。
整理了一些知识内容,留下了这篇文章。
子查询,是指嵌套包含在另一个
SELECT
语句中的语句。
如下例子:
# 子查询的常见例子
SELECT * FROM [table_name_1] WHERE [column_name_1] IN (
SELECT [column_name_2] FROM [table_name_2]
上面的SQL语句就是子查询的常见例子。
在这个例子中,一共包含了两句SELECT
查询语句,他们形成了语句嵌套的关系。
其中,SELECT * FROM [table_name_1] WHERE [column_name_1] IN ([subquery])
这句查询语句我们称之为外部查询(Outer Query)。
内部的SELECT [column_name_2] FROM [table_name_2]
,我们称之为子查询(Subquery),或者也可以称为内部查询。
需要特别注意的是,子查询的使用需要将子查询语句包裹在括号内。
子查询的执行顺序和子查询的相关性有关。
根据子查询和外部查询的相关性来说,我们可以将子查询分为相关子查询(Correlated Subquery)和非相关子查询(Noncorrelated Subquery)两类。
非相关子查询
非相关子查询中,子查询独立于外部查询。执行顺序上,由内而外,先执行子查询语句,后执行外部查询,子查询只执行一次,执行完毕后将结果集传递给外部查询。语句的执行过程中,涉及到子查询的结果集由内而外的传递。
我们以前面 子查询 的展示例子作为这里的例子。它就是一个非相关子查询,执行过程为:
执行内部子查询。子查询从table_name_2
表格中检索出column_name_2
的列的结果集;
内部子查询检索出来的结果集将会传递给外查询的WHERE
子句作为IN
操作符的操作值;
外部查询根据自己的WHERE
子句的过滤逻辑结合内部子查询传递的结果集得出自己的检索结果集,返回结果集;
相关子查询
和非相关子查询不同,由于调用了外部查询的行数据,相关子查询的执行依赖于外部查询语句。执行顺序上,由外而内,先执行外部查询语句得到行数据,在行数据的基础上后执行子查询,外部查询执行一行,子查询就执行一次。语句执行的过程中,涉及到外部查询的行数据由外而内再到外的传递。
# 相关子查询
SELECT [column_name_1], (
SELECT COUNT(*)
FROM [table_name_2]
WHERE [table_name_2].[column_name_2] = [table_name_1].[column_name_1]
) AS [column_name_alias]
FROM [table_name_1];
上面的语句即为相关子查询的典型例子。他的执行过程为:
执行外部查询。外部查询从table_name_1
表格中检索出一条行数据;
外部查询检索出来的行数据将会传递给内部子查询的WHERE
子句作为列[table_name_1].[column_name_1]
的值;
结合外部查询传递进来的值,内部子查询根据WHERE
子句的过滤条件检索出符合条件的结果集并进行聚合计算得到一个数量聚合值,传递这个聚合值给外部查询;
外部查询将传递出来的值作为列column_name_alias
的值,得到一条行结果数据;
重复执行步骤1到步骤4,检索出下一条行数据传递给内部子查询从而得到一条新的行结果数据;
返回所有的行结果数据组成的结果集;
子查询允许我们将多条检索语句嵌套组合成了一条语句来在DBMS中执行。
但是,我们需要特别注意子查询嵌套的深度和语句复杂度的控制。过度的子查询嵌套会影响语句的执行效率,从而导致慢SQL的出现。同时,嵌套过于复杂的子查询语句容易艰涩难懂,阅读困难,在这方面,格式化语句、适当的使用缩进,能够有不错的帮助。
子查询的执行顺序需要根据子查询的相关性进行思考和讨论。
《MySQL必知必会》
MySQL Documentation