Contents
  1. 1. 子查询的优点和限制
  2. 2. 独立子查询
  3. 3. 相关子查询

MySQL数据库被诟病的一个地方就是子查询。很多开发人员和DBA认为MySQL数据库只是拥有该功能,但性能很差,是一项很不实用的功能。在实际开发中开发人员很少使用子查询,因为在应用程序中使用子查询后,SQL语句的查询性能变得非常糟糕。

子查询的优点和限制

子查询是指在一个SELECT语句中嵌套另一个SELECT语句。
MySQL数据库从4.1版本开始支持子查询,并且支持所有SQL标准的子查询,也扩展了一些其独有的子查询标准。下面是一个子查询:
SELECT FROM T1 WHERE COLUMN1=(SELECT COLUMN1 FROM T2);
在这个示例中,SELECT
FROM T1是外部查询(outer query),select column1 from t2是子查询。一般来说,称子查询嵌套(nested)于外部查询中。实际上也可以将两个或两个以上的子查询进行嵌套。需要注意的,子查询必须包含括号。
通常来说,使用子查询的好处如下:

  • 子查询允许结构化的查询,这样就可以把一个查询语句的每个部分隔开。
  • 子查询提供了另一种方法来执行有些需要复杂的join和union来实现的操作。
  • 在许多人看来,子查询可读性较高。而实际上,这也是子查询的由来。

一个子查询会返回一个标量(单一值)、一个行、一个列或一个表(一行或多行及一列或多列),这些子查询被称为标量、列、行和表子查询。可返回一个特定种类结果的子查询经常只用于特定的语境中。
子查询的限制是其外部语句必须是以下语句之一:SELECT、INSERT、UPDATE、DELETE、SET或DO。还有一个限制是,目前用户不能既在一个子查询中修改一个表,又在同一个表中进行选择,虽然这样的操作可用于普通的DELETE、INSERT、REPLACE和UPDATE语句,但是对其子查询不可以同时进行这样的操作。

子查询中使用 IN、ANY、SOME 和 ALL 操作符

由于子查询返回的结果集是 N 行一列,因此不能直接使用 = > < >= <= <> 这些比较标量结果的操作符。在子查询中可以使用 IN、ANY、SOME 和 ALL 操作符:

IN:在指定项内,同 IN(项1,项2,…),IN是“=ANY的别名”,NOT IN 是“<> ALL”的别名
ANY:与比较操作符联合使用,表示与子查询返回的任何值比较为 TRUE ,则返回 TRUE 。
SOME:ANY 的别名,较少使用。
ALL:与比较操作符联合使用,表示与子查询返回的所有值比较都为 TRUE ,则返回 TRUE 。

独立子查询

子查询可以按两种方式进行分类。若按照期望值的数量,可以将子查询分为标量子查询和多值子查询;若按查询对外部查询的依赖可分为独立子查询(self-contained subquery)和相关子查询(correlated subquery)。标量子查询和多值子查询可以是独立子查询,也可以是相关子查询。

独立子查询是不依赖外部查询而运行的子查询。与相关子查询相比,独立子查询更便于SQL语句的调试。

标量子查询可以出现在查询中希望产生标量值的任何地方,而多值子查询可以出现在查询中希望产生多值集合的任何地方。只要标量子查询返回的是单个值或NULL值,就说明该查询是有效的。如果标量子查询返回多个值,则MySQL数据库将抛出错误。如以下两句标量子查询都是正确的。

SELECT 'a' = (SELECT 'a') AS t;
SELECT 'a' = (SELECT NULL) AS t;

而下面的子查询会抛出异常:

mysql> SELECT 'a' = (SELECT 'a' UNION ALL SELECT 'b') AS t;
ERROR 1242 (21000): Subquery returns more than 1 row

因为子查询产生的派生表t返回两个值(a和b),而外部查询期望的是一个标量值,因此在运行时,MySQL数据库抛出异常,提示该子查询返回多行数据。
目前已经介绍了独立子查询的基本使用方法,接着继续讨论更加复杂的独立子查询问题。这里将从一个属于关系分区的问题开始。关系分区问题有很多细微的差别和实际的应用,从逻辑上看,关系分区就是一个集合划分另外一个集合,并产生一个结果集。
例如,从tpcc数据库中返回每个美国员工至少处理过一个订单的所有客户。这里需要从所有美国员工的集合中来划分订单的集合,并得到期望匹配的客户集合。这个操作并不简单,因为需要对每一个客户检查多行以判断是否有匹配。

MySQL优化器对于IN子句,如果不是显式的列表定义,如IN(‘a’,’b’,’c’),那么IN子句都会转换为EXISTS的相关子查询。

相关子查询

相关子查询(Dependent Subquery 或 Correlated Subquery)是指引用了外部查询列的子查询,即子查询会对外部查询的第行进行一次计算。但是在优化器内部,这是一个动态的过程随情况的变化会有所不同,通过不止一种优化方式来处理相关子查询。

Contents
  1. 1. 子查询的优点和限制
  2. 2. 独立子查询
  3. 3. 相关子查询