相关子查询和嵌套子查询两者之间的区别
表的结构如下:
mysql> select * from product;
+----+------+-------+-----+
| id | name | price | num |
+----+------+-------+-----+
| 1 | 伊利 | 68 | 1 |
| 2 | 蒙牛 | 88 | 1 |
| 3 | nike | 888 | 2 |
| 4 | 阿迪 | 688 | 2 |
| 5 | kris | 1888 | 3 |
| 6 | tom | 2888 | 3 |
| 7 | sam | 1688 | 3 |
+----+------+-------+-----+
嵌套子查询:执行不依赖于外部的查询。
执行顺序:先子查询然后在是主查询。
子查询的结果不会被显示,会将其传递给外部查,作为外部查询的条件来输出
例子:查询所有价格高于平均价格的商品信息。
mysql> select * from product where price > (select avg(price) from product);
+----+------+-------+-----+
| id | name | price | num |
+----+------+-------+-----+
| 5 | kris | 1888 | 3 |
| 6 | tom | 2888 | 3 |
| 7 | sam | 1688 | 3 |
+----+------+-------+-----+
先执行子查询得到product表中商品的平均价格 然后通过price>avg的条件控制输出主查询的结果。
相关子查询:执行依赖于外部查询。(相关子查询是一个子查询中引用了某张表且这张表也在子查询外部被使用到。)
执行顺序:先是主查询然后在是子查询。
执行过程:
从主查询中取出一个元组(表中的行),将元组相关的列的值传递给子查询
子查询将列的值作为条件得到结果
主查询根据子查询得到的结果或者结果集得到满足条件的行,selece控制显示
然后主查询取出下一个元组继续1-3步骤,直到所有元组全部处理完毕。
例:取出不同num中的最高价格的商品信息,在子查询中使用了外部表的num字段,p.num。相关子查询
和普通子查询
(也叫非相关子查询
)的差别就在于这子查询中是否有对外部查询中涉及到的表的引用。
mysql> select * from product p where p.price = (select max(price) from product where num=p.num);
+----+------+-------+-----+
| id | name | price | num |
+----+------+-------+-----+
| 2 | 蒙牛 | 88 | 1 |
| 3 | nike | 888 | 2 |
| 6 | tom | 2888 | 3 |
+----+------+-------+-----+
执行过程:
1.取出这个元组:| 1 | 伊利 | 68 | 1 | num=1
2.select max(price) from product where num=1;
3.select * from produt p where p.price=88;
4.得到商品信息:| 2 | 蒙牛 | 88 | 1 |
5.依次取出接下来的元组然后执行1-4.
相关子查询执行步骤拆解
相关子查询被用来做逐行的处理,子查询会为外部查询出来的每一行执行内部SQL。(外部语句也可为update或delete语句)
可拆分成下面三个步骤:
- 外部查询拿到所有行
- 内部查询使用外部查询出来的每一行来执行自己逻辑
- 内部查询有结果返回则当前外部行被保留最终返回否则继续执行下一行
相关子查询和嵌套查询的区别
- 执行顺序:相关子查询是由外部查询驱动内部查询。 而正常的嵌套查询中,内部查询首先被立即执行,返回的值被外部查询使用并执行外部查询。
- 依赖性:相关子查询内部查询依赖于外部查询进行处理,而在嵌套查询中外部查询依赖于内部查询。
- 性能:使用相关子查询会使性能降低,因为它执行的次数远远大于嵌套查询的次数,可以使用exit优化,并且最好小表驱动大表