1.子查询语法
在一个查询语句A里的某个位置也可以有另一个查询语句B,这个出现在A语句的某个位置中的查询B就被称为子查询,A也被称之为外层查询。子查询可以在一个外层查询的各种位置出现,比如:
1)SELECT子句中
也就是我们平时说的查询列表中,比如这样:
SELECT(SELECT m1 FROM e1 LIMIT 1);
其中的(SELECT m1 FROM e1LIMIT 1)就是子查询。
2)FROM子句中
SELECT m, n FROM (SELECT m2 + 1 AS m, n2 AS n FROM e2 WHERE m2 > 2) AS t;
这个例子中的子查询是:(SELECT m2+1 AS m, n2 AS n FROM e2 WHERE m2 > 2)
这里可以把子查询的查询结果当作是一个表,子查询后边的AS t表明这个子查询的结果就相当于一个名称为t的表,这个名叫t的表的列就是子查询结果中的列,比如例子中表t就有两个列:m列和n列。
这个放在FROM子句中的子查询本质上相当于一个表,但又和我们平常使用的表有点儿不一样,MySQL把这种由子查询结果集组成的表称之为 派生表 。
3)WHERE**或ON子句中**
把子查询放在外层查询的WHERE子句或者ON子句中可能是我们最常用的一种使用子查询的方式了,比如这样:
SELECT * FROM e1 WHERE m1 IN (SELECT m2 FROM e2)
这个查询表明我们想要将(SELECT m2FROM e2)这个子查询的结果作为外层查询的IN语句参数,整个查询语句的意思就是我们想找e1表中的某些记录,这些记录的m1列的值能在e2表的m2列找到匹配的值。
4)ORDER BY**子句、GROUP BY子句中**
虽然语法支持,但没啥意义。
还有一些其他的子查询,这里不一一列举
2.子查询在MySQL中是怎么执行的
想象中子查询的执行方式是这样的:
如果该子查询是不相关子查询,比如下边这个查询:
SELECT * FROM s1 WHERE order_note IN (SELECT order_note FROM s2);
先单独执行(SELECTorder_note FROM s2)这个子查询。
然后在将上一步子查询得到的结果当作外层查询的参数再执行外层查询
最后根据子查询的查询结果来检测外层查询WHERE子句的条件是否成立,如果成立,就把外层查询的那条记录加入到结果集,否则就丢弃。
但真的是这样吗?其实MySQL用了一系列的办法来优化子查询的执行,大部分情况下这些优化措施其实挺有效的,下边我们来看看各种不同类型的子查询具体是怎么执行的。
不同的子查询
1)按返回的结果集区分子查询
因为子查询本身也算是一个查询,所以可以按照它们返回的不同结果集类型而把这些子查询分为不同的类型:
1.1)标量子查询
那些只返回一个单一值的子查