一,子查询定义:
子查询就是嵌套在主查询中的查询。
子查询可以嵌套在主查询中所有位置,包括SELECT、FROM、WHERE、GROUP BY、HAVING、ORDER BY。
但并不是每个位置嵌套子查询都是有意义并实用的。
二,子查询的返回:
一个子查询会返回一个标量(单一值)、一个行、一个列或一个表(一行或多行及一列或多列)。这些子查询被称为标量、列、行和表子查询
1,单行单列,聚合(标量):
返回的结果集为单个的子查询,叫做单行子查询。单行比较符有: =、 >、>=、<、<=、!=
2,单行多列:
SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2); SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);
如果在表t2的一个行中,column1=1并且column2=2,则查询结果均为TRUE。
表达式(1,2)和ROW(1,2)有时被称为行构造符。两者是等同的,在其它的语境中,也是合法的。例如,以下两个语句在语义上是等同的(但是目前只有第二个语句可以被优化):
SELECT * FROM t1 WHERE (column1,column2) = (1,1); SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;
3,多行单列与多行多列:
返回的结果集为多个的子查询,为多行子查询,多行子比较符有 IN(等于列中任意一个)、ANY(和子查询返回的某个值比较),ALL(和子查询返回的所有值比较)
NOT IN是<> ALL的别名
IN是=ANY的别名
三,EXISTS和NOT EXISTS
如果一个子查询返回任何的行,则EXISTS subquery为FALSE。例如:
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);
四,关联子查询
相关联的子查询是一个包含对表的引用的子查询。该表也显示在外部查询中。例如:
SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);
注意,即使子查询的FROM子句不提及表t1,该子查询也会包含一个对t1中一列的引用。所以,MySQL看上去位于子查询的外部,并在外部查询中查找t1。
假设表t1包含一行,在此行中column1=5并且column2=6;同时,表t2包含一行,在此行中column1=5并且column2=7。简单的表达式... WHERE column1 = ANY (SELECT column1 FROM t2)会为TRUE。但是在本例中,在子查询中的WHERE子句为FALSE(因为(5,6)不等于(5,7)),所以子查询总体上为FALSE。
范围划分规则:MySQL从内到外进行评估。例如:
SELECT column1 FROM t1 AS x WHERE x.column1 = (SELECT column1 FROM t2 AS x WHERE x.column1 = (SELECT column1 FROM t3 WHERE x.column2 = t3.column1));
在本语句中,x.column2必须是表t2中的列,因为SELECT column1 FROM t2 AS x ...对t2进行了重命名。它不是表t1中的列,因为SELECT column1 FROM t1 ...是一个更靠外的外部查询。
对于HAVING或ORDER BY子句中的子查询,MySQL也会在外部选择清单中寻找列名称。
对于特定的情况,相关联的子查询被优化。例如:
val IN (SELECT key_val FROM tbl_name WHERE correlated_condition)
否则,这些子查询效率不高,可能速度会慢。把查询作为联合进行改写可能会改进效率。
相关联的子查询不能从外部查询中引用总计函数的结果。
五,FROM子句中的子查询
在SELECT语句的FROM子句中,子查询是合法的。实际的语法是:
SELECT ... FROM (subquery) [AS] name ...
[AS] name子句是强制性的,因为FROM子句中的每个表必须有一个名称。在子查询选择列表中的任何列都必须有唯一的名称。您可以在本手册中的其它地方找到对本语法的说明。在该处,所用的词语是“导出表”。
为了进行详细说明,假设您有如下一个表:
CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);
下面使用了示例表,解释了在FROM子句中如何使用子查询:
INSERT INTO t1 VALUES (1,‘1‘,1.0); INSERT INTO t1 VALUES (2,‘2‘,2.0); SELECT sb1,sb2,sb3 FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb WHERE sb1 > 1; //结果:2, ‘2‘, 4.0。
下面是另一个例子:假设您想了解一个分类后的表的一组和的平均值。采用如下操作:
SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;
不过,本查询提供所需的信息:
SELECT AVG(sum_column1) FROM (SELECT SUM(column1) AS sum_column1 FROM t1 GROUP BY column1) AS t1;
注意,在子查询中使用的列名称(sum_column1)被整理到外部查询中。
FROM子句中的子查询可以返回标量、列、行或表。FROM子句中的子查询不能为有关联的子查询。
即使对EXPLAIN语句(即建立临时导出表),FROM子句中的子查询也会被执行。这是因为在优化过程中,上一级的查询需要有关所有表的信息。
原文地址:https://www.cnblogs.com/tkzc2013/p/10767336.html