SQL里面嵌套子查询这是非常普遍的写法。
下面是有关子查询的一些说明:
子查询又称内部查询,而包含子查询的语句称之外部查询(又称主查询)。
所有的子查询可以分为两类,即相关子查询和非相关子查询。
非相关子查询是独立于外部查询的子查询,子查询总共执行一次,执行完毕后将值传递给外部查询。
相关子查询的执行依赖于外部查询的数据,外部查询执行一行,子查询就执行一次。
这个解释没问题,但是上周碰到个问题,2层子查询,其中相关子查询作为内层子查询,外层的是非相关的。这样的子查询到底算相关还是非相关呢?
select a.pro_name, a.pro_type, a.pro_price
from supmka a, supmkb_1 b
where a.pro_name = b.pro_name
and a.pro_type = b.pro_type
and a.pro_price = (select d.pro_price
from (select distinct c.pro_price
from supmkb_2 c
where c.pro_no = b.pro_no) d
where rownum = 1);
红色标注的子查询是相关的(内层的表c和主查询的表b关联),而外层蓝色的是非相关的。
查看执行计划之后,发现优化器先做的红色部分的查询,然后再做蓝色,再做关联。也就是说,红色部分的c.pro_no = b.pro_no,优化器忽略了(版本是Oracle Database 10g Enterprise Edition Release 10.2.0.1.0)
这样的数据查出来肯定有问题。
如果把distinct的位置换一下,
select a.pro_name, a.pro_type, a.pro_price
from supmka a, supmkb_1 b
where a.pro_name = b.pro_name
and a.pro_type = b.pro_type
and a.pro_price = (select distinct d.pro_price
from (select c.pro_price
from supmkb_2 c
where c.pro_no = b.pro_no) d
where rownum = 1);
优化器会先做关联查询。把c.pro_no = b.pro_no条件带进去做查询了。
所以大家不要写这种关联嵌套非关联的子查询,优化器都不知道怎么处理了。
另外在做实验期间,还发现一个问题:
在Oracle Database 10g Enterprise Edition Release 10.2.0.3.0上执行
select a.pro_name, a.pro_type, a.pro_price
from supmka a, supmkb_1 b
where a.pro_name = b.pro_name
and a.pro_type = b.pro_type
and a.pro_price = (select d.pro_price
from (select distinct c.pro_price
from supmkb_2 c
where c.pro_no = b.pro_no) d
where rownum = 1);
会报ora-00904,b.pro_no字段没有定义的错误。也就是说,优化器还是先执行了红色部分的SQL,但是并没有把where c.pro_no = b.pro_no条件忽略,导致了00904的错误。
而在10.2.0.1.0版本上,优化器直接忽略了where c.pro_no = b.pro_no条件。
实际上这个SQL写得非常不好。zizi只是抱着一种蛋疼的精神分析了一下SQL执行顺序,也算打发无聊的时间吧
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/16591471/viewspace-695491/,如需转载,请注明出处,否则将追究法律责任。
转 http://blog.itpub.net/16591471/viewspace-695491/