写这个也不是为了给什么人看,就当是自己工作的一些总结吧.
exists,工作中应该看个人写法,但是涉及后续进阶,哪怕自己不写,至少能看懂别人的代码,而且exists有时候效率会高于in,粗略写写,实际我不大用......
(1)原理
执行顺序如下:
1.首先执行一次外部查询
2.对于外部查询中的每一行分别执行一次子查询,而且每次执行子查询时都会引用外部查询中当前行的值。
3.使用子查询的结果来确定外部查询的结果集。 如果外部查询返回100行,SQL 就将执行101次查询,一次执行外部查询,然后为外部查询返回的每一行执行一次子查询。
如果内层子查询有行返回,则返回ture,进行外层当前行语句的执行.
如果内层子查询无行返回,则返回flase,进行外层当前行语句的执行,当然不会执行,返回为空
一种通俗的可以理解为:将外查询表的每一行,代入内查询作为检验,如果内查询返回的结果取非空值,则EXISTS子句返回TRUE,这一行行可作为外查询的结果行,否则不能作为结果。
以下粘贴,留作备注. 确实涉及到了指针,数据库的指针应该就是游标,大概就是iterator把......
分析器会先看语句的第一个词,当它发现第一个词是SELECT关键字的时候,它会跳到FROM关键字,然后通过FROM关键字找到表名并把表装入内存。接着是找WHERE关键字,如果找不到则返回到SELECT找字段解析,如果找到WHERE,则分析其中的条件,完成后再回到SELECT分析字段。最后形成一张我们要的虚表。
WHERE关键字后面的是条件表达式。条件表达式计算完成后,会有一个返回值,即非0或0,非0即为真(true),0即为假(false)。同理WHERE后面的条件也有一个返回值,真或假,来确定接下来执不执行SELECT。
分析器先找到关键字SELECT,然后跳到FROM关键字将STUDENT表导入内存,并通过指针找到第一条记录,接着找到WHERE关键字计算它的条件表达式,如果为真那么把这条记录装到一个虚表当中,指针再指向下一条记录。如果为假那么指针直接指向下一条记录,而不进行其它操作。一直检索完整个表,并把检索出来的虚拟表返回给用户。EXISTS是条件表达式的一部分,它也有一个返回值(true或false)。
(1)第一种情况
select * from a1
where EXISTS (select 1 from b1 where a1.aid = b1.aid)
首先执行外层语句
1.即select * from a1,之后外层的每一行都会对内层语句做一次子查询.也可以说是循环.
2从表a1中第一条数据1 a1开始,进入exsits函数,当前子查询where中,有没有b1.aid=1的数据?因为存在,则返回ture. 这个1也就是外查询的第一条数据的a1.aid.
3.之后外查询第二行,子查询存在满足条件的值所以都返回.
4.第三行,此时a1.aid=3 子查询里面变成 where b1.aid=3 不存在此值,返回flase,所以没有第三个记录
5.补充一下,比如查询第二行的时候.(select 1 from b1 where a1.aid = b1.aid) 即子查询中应该也是一个循环,,外面的a1.aid=2 此时子查询运行到b1的第一行,即b1.aid=1,flase不满足,之后运行到子查询b1的第二行 b1.aid=2 ture满足外面的a1.aid=2 true返回.结束里层循环.
其实里面的循环也是进行一次又一次判断,返回ture就直接结束,flase继续执行里面的下一条数据.大概类似于双层for循环把.
(2)第二种情况
select * from a1
where EXISTS (select 1 from b1 where a1.aid = 1)
1.主查询执行
2.a1第一行数据 此时 a1.aid=1 与子查询里面的数据呼应 ture 返回
3.第二行,此时a1.aid=2 子查询不满足 flase
4.第三行,同上
(3)第三种情况
select * from a1
where EXISTS (select 1 from b1 where b1.aid = 1)
1.主查询执行
2.a1第一行数据 此时子查询存在b1.aid=1的数据 ture返回
3.第二行,此时子查询再次来到子查询b1表中的第一行,满足b1.aid=1返回
4.第三行,同上
(4)效率问题
这个还是理解记比较好记
where是先执行子查询where子句,再执行主句 所以在主表大 而子查询中表小时候,效率高
exsits相反, 主表小,而子查询表大时候,效率高
结束,就这样总结吧,实际用的也不多........