sql优化必会--exists代替in改写sql 概述
⼀般在做SQL优化的时候讲究使⽤EXISTS带替代IN的做法,理由是EXISTS执⾏效率要⽐IN ⾼。
个⼈理解:
IN表⽰范围,指某⼀字段在某⼀范围之内,这个范围⼀般使⽤⼦查询来获取,由此可知IN⼦查询返回的结果应该就是这个范围集。
EXISTS表⽰存在,指⾄少存在⼀处,这个条件由EXISTS⼦查询来完成,但是在这⾥EXISTS⼦查询返回的结果却不再是⼀个结果集,⽽是⼀个布尔值(true或false),其实这个挺好理解的,EXISTS就表⽰如果⼦查询能查到值则返回true,则执⾏EXISTS之前的语句。
测试数据
员⼯参数课程培训数据,两次不同课程培训分别存在CLASS_A 和 CLASS_B 两张表中。CLASS_A:
exists子查询CLASS_B:
需求:查同时参加了两门课程的员⼯。
两种⽅式实现
下⾯分别使⽤in 和 exists两种⽅式实现。
1、in ⽅式查询
SELECT *FROM class_aWHERE id IN ( SELECT id FROM class_b);
2、exists ⽅式查询
SELECT *FROM class_a AWHERE EXISTS (  SELECT *  FROM class_b B WHERE A.id = B.id);
说明:
上述两种⽅法查询结果⼀样,但exists ⽅式速度要快。分析如下:
1)如果连接列id 上有索引,那么查询CLASS_B时,⽆需查询实际表,仅需要查索引就可以了。
2)使⽤exists ,那么只有查到⼀⾏数据满⾜条件就会终⽌查询,不会产⽣临时表。
3)使⽤in查询时,数据库⾸先会执⾏⼦查询,然后将结果保存在临时表中,然后扫描整个临时表,很多情况下⾮常耗费资源。
如何⽤exists来代替in
假如有⼀个表user,它有两个字段id和name,要查询名字中带a的⽤户信息:
最简单的SQL:select * from user where name like '%a%'; 使⽤IN的SQL:select u.* from user u where u.id in (select uu.id from user uu where uu.name like '%a%');
将使⽤IN的SQL修改为使⽤EXISTS的SQL该怎么写呢?
⼀开始我直接将u.id in 替换为EXISTS,获得如下语句:
select u.* from user u where exists(select uu.id from user uu where uu.name like '%a%');
经过测试发现输出结果错误,该语句将所有的⽤户全部⼀个不漏的查询出来了,相信你也发现了问题,后来我对上述语句做了修改如下:
select u.* from user u where exists (select uu.id from user uu where uu.name like '%a%' and uu.id=u.id);
只是在⼦查询中添加了“and uu.id=u.id”,结果查询结果正确。
总结:EXISTS⼦查询可以看成是⼀个独⽴的查询系统,只为了获取真假逻辑值,EXISTS⼦查询与外查询查询的表是两个完全独⽴的毫⽆关系的表(当第⼆个表中的name中有包含a的姓名存在,那么就执⾏在第⼀个表中查询所有⽤户的操作),当我们在⼦查询中添加了id关联之后,EXISTS⼦查询与外查询查询的表就统⼀了,是⼆者组合组建的虚表,是同⼀个表(这样当⼦查询查询到虚表中当前⾏的uu.name中包含a时,则将虚表当前⾏中对应的u.id与u.name查询到了)
所以⼀切的重点就在这个ID关联之上,添加ID关联,数据库会先将两张表通过ID关联组合成⼀张虚表,所有的查询操作都在这张虚表上完成,操作的是同⼀张表,当然就不会出现之前的那种情况了!
总结
exists ⽅式查询⽐ in ⽅式查询效率⾼,但in 可读性较好。建议尽可能使⽤exists⽅式,避免使⽤⼦查询,除⾮in 的参数为数值列表。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。