in是把外表和内表作hash连接,而exists是对外表作loop循环。
确定给定的值是否与子查询或列表中的值相匹配。in在查询的时候,首先查询子查询的表,然后将内表和外表做一个笛卡尔积,然后按照条件进行筛选。所以相对内表比较小的时候,in的速度较快。
具体sql语句如下:
1 SELECT 2 * 3 FROM 4 `user` 5 WHERE 6 `user`.id IN ( 7 SELECT 8 `order`.user_id 9 FROM10 `order`
exist是指定一个子查询,检测行的存在。遍历循环外表,然后看外表中的记录有没有和内表的数据一样的。匹配上就将结果放入结果集中。
具体sql语句如下:
1 SELECT 2 `user`.* 3 FROM 4 `user` 5 WHERE 6 EXISTS ( 7 SELECT 8 `order`.user_id 9 FROM10 `order`11 WHERE12 `user`.id = `order`.user_id
1.exist,notexist一般都是与子查询一起使用.In可以与子查询一起使用,也可以直接in(a,b.....)\x0d\x0a\x0d\x0a2.exist会针对子查询的表使用索引.notexist会对主子查询都会使用索引.in与子查询一起使用的时候,只能针对主查询使用索引.notin则不会使用任何索引.注意,一直以来认为exists比in效率高的说法是不准确的。\x0d\x0ain是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。\x0d\x0a如果查询的两个表大小相当,那么用in和exists差别不大。\x0d\x0a如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:\x0d\x0a例如:表A(小表),表B(大表)1:select*fromAwhereccin(selectccfromB)\x0d\x0a效率低,用到了A表上cc列的索引;select*fromAwhereexists(selectccfromBwherecc=A.cc)\x0d\x0a效率高,用到了B表上cc列的索引。\x0d\x0a相反的2:select*fromBwhereccin(selectccfromA)\x0d\x0a效率高,用到了B表上cc列的索引;select*fromBwhereexists(selectccfromAwherecc=B.cc)\x0d\x0a效率低,用到了A表上cc列的索引。\x0d\x0anotin和notexists如果查询语句使用了notin那么内外表都进行全表扫描,没有用到索引;而notextsts的子查询依然能用到表上的索引。所以无论那个表大,用notexists都比notin要快。\x0d\x0a3.exist与in都可以实现一个目的.二者都可以用来过滤数据.\x0d\x0a示例:\x0d\x0a\x0d\x0aselectcount(1)fromt1--160W\x0d\x0aselectcount(1)fromt2--90W\x0d\x0a\x0d\x0aSELECTcount(1)\x0d\x0aFROMt1a\x0d\x0aWHEREEXISTS(SELECTaccountid\x0d\x0aFROMt2b\x0d\x0aWHEREa.keyid=b.keyidANDa.ideaid=b.ideaid)--主大子小,不适合使用exist,因为exist只会利用子表t2的复合索引keyid+ideaid,而子表内容要小与主表,主表由于无法使用索引,查询效率低下.\x0d\x0a\x0d\x0aselectcount(1)fromt1awhereaccountidin(SELECTaccountid\x0d\x0aFROMt2b\x0d\x0aWHEREa.keyid=b.keyidANDa.ideaid=b.ideaid)--主大子小,适合用in,因为in只会使用主表t1里面的复合主键keyid-ideaid,在主表大于子表的情况下,会很好的利用主表的索引.\x0d\x0a\x0d\x0a--后二条sql的执行结果都是一样的.说明exist与in在用法上可以达到一个目的,不同的地方是\x0d\x0a--1.性能的考虑此时就按子表大主表小用exist,子表小主表大用in的原则就可以.\x0d\x0a--2.写法的不同,exist的where条件是:"......whereexist(.....wherea.id=b.id)"\x0d\x0a--in的where条件是:"......whereidin(selectid....wherea.id=b.id)"\x0d\x0a\x0d\x0a4.exist的原理:\x0d\x0aexists做为where条件时,是先对where前的主查询询进行查询,然后用主查询的结果一个一个的代入exists的查询进行判断,如果为真则输出当前这一条主查询的结果,否则不输出\x0d\x0a比如\x0d\x0a如下:\x0d\x0a表A\x0d\x0aIDNAME\x0d\x0a1A1\x0d\x0a2A2\x0d\x0a3A3\x0d\x0a\x0d\x0a表B\x0d\x0aIDAIDNAME\x0d\x0a11B1\x0d\x0a22B2\x0d\x0a32B3\x0d\x0a\x0d\x0a表A和表B是一对多的关系A.ID-->B.AID\x0d\x0a\x0d\x0aSELECTID,NAMEFROMAWHEREEXISTS(SELECT*FROMBWHEREA.ID=B.AID)\x0d\x0a执行结果为\x0d\x0a1A1\x0d\x0a2A2\x0d\x0a原因可以按照如下分析\x0d\x0aSELECTID,NAMEFROMAWHEREEXISTS(SELECT*FROMBWHEREB.AID=1)\x0d\x0a-->SELECT*FROMBWHEREB.AID=1有值返回真所以有数据\x0d\x0a\x0d\x0aSELECTID,NAMEFROMAWHEREEXISTS(SELECT*FROMBWHEREB.AID=2)\x0d\x0a-->SELECT*FROMBWHEREB.AID=2有值返回真所以有数据\x0d\x0a\x0d\x0aSELECTID,NAMEFROMAWHEREEXISTS(SELECT*FROMBWHEREB.AID=3)\x0d\x0a-->SELECT*FROMBWHEREB.AID=3无值返回真所以没有数据\x0d\x0a\x0d\x0aNOTEXISTS就是反过来\x0d\x0aSELECTID,NAMEFROMAWHERENOTEXIST(SELECT*FROMBWHEREA.ID=B.AID)\x0d\x0a执行结果为\x0d\x0a3A3\x0d\x0a5.in与=的区别\x0d\x0aselectnamefromstudentwherenamein('zhang','wang','li','zhao')\x0d\x0a与\x0d\x0aselectnamefromstudentwherename='zhang'orname='li'orname='wang'orname='zhao'\x0d\x0a的结果是相同的。\x0d\x0ain的字段也可以与其它字段建复合索引.\x0d\x0a比如\x0d\x0aT1包含下面key,accountd,groupid.\x0d\x0a\x0d\x0aSELECT*\x0d\x0aFROMT1a\x0d\x0aWHEREa.groupid=2001\x0d\x0aANDa.accountid=1001\x0d\x0aANDa.keyIN('abc','def','ala')\x0d\x0a\x0d\x0a--上面的sql可以将accountid,key建成复合索引.欢迎分享,转载请注明来源:内存溢出
评论列表(0条)