mysql中exists与in的使用

exists对外表用loop逐条查询,每次查询都会查看exists的条件语句,当exists里的条件语句能够返回记录行时(无论记录行是多少,只要能返回),条件就为真,返回当前loop到的这条记录,反之如果exists里的条件语句不能返回记录行,则当前loop到的这条记录被丢弃,exists的条件就像一个bool条件,当能返回结果集则为true,不能返回结果集则为false

如下:

select * from user where exists(select 1);

对user表的记录逐条取出,由于子条件中的select 1永远能返回记录行,那么user表的所有记录都将被加入结果集,所以与select * from user;是一样的

又如下

select * from user where exists(select * from user where userId = 0);

可以知道对user进行loop时,检查条件语句(select * from user where userId = 0),由于userId永远不为0,所以条件永远为false,那么user表的所有记录都将被丢弃

not exists与exists相反,也就是当exists条件有结果返回时,loop到的记录将被丢弃,否则将loop到的记录加入结果集

总的来说,如果A表有n条记录,那么exists查询就是将这n条数据逐条取出,然后判断n遍exists条件

 

in查询相当于多个or条件的叠加

如下:

select * from user where userId in (1,2,3);

等效于

select * from user where userId =1 or userId = 2 or userId = 3;

not in与in相反,如下

select * from user where userId not in(1,2,3);

等效于

select * from user where userId !=1 and userId !=2 and userId !=3;

总的来说,in查询就是先将子查询条件的记录全部查出来,假设结果集为B,共有m条记录,然后在将子查询条件结果分解成m个,再进行m次查询

 

值得一提的是,in查询的子条件返回结果必须只有一个字段,例如

select * from user where userId in(select id from B);

而不能是

select * from user where userId in(select id,age from B);

而exists就没有这个限制

 

下面来考虑exists和in的性能

如下:

1,select * from A where exists (select * from B where B.id = A.id)

2,select * from A where A.id in(select id from B);

查询1转化为伪代码:

 

for($i=0;$i<count(A);$i++){
     $a = get_record(A,$i);//从A表逐条获取记录
     if(B.id = $a['id']){//如果子条件成立
           $result[] = $a; 
     }
}
return $result;

可以看到,查询1主要用到的是B表的索引,A表如何对查询的效率影响应该不大

 

假设B表的所有id为1,2,3,产寻2可以转化为

select * from A where A.id = 1 or A.id = 2 or A.id = 3;

这里主要用到了A的索引,B表如何对查询影响不大

 

再看not exists和not in

1,select * from A where not exists (select * from B where B.id = A.id);

2,select * from A where A.id not in(select id from B);
查询1,还是用了B的索引

查询2,可以转换为

select * from A where A.id !=1 and A.id !=2 and A.id != 3;

可以知道not in是个范围查询,这种!=的范围查询无法使用任何索引,等于说B表的每条记录,都要在A表里遍历一次,查看A表里是存在这条记录

故not exists比not in效率高

 

如果查询的两个表大小相当,那么用in和exists差别不大

如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in:

例如:表A(小表),表B(大表)

1:

select * from A where cc in(select cc from B)效率低,用到了A表上的cc列索引;

select * from A where exists(select cc from B where cc=A.cc)效率高,用到了B表上的cc列索引

 

2:

select * from B where cc in(select cc from A)效率高,用到了B表上cc列索引

select * from B where exists(select cc from A where cc=B.cc)效率低,用到了A表上cc列索引

 

not in和not exists

如果查询语句使用了not in那么内外表都进行全表扫描,没有用到索引;而not exists的子查询依然能用到表上的索引

所以无论那个表大,not exists都比not in要快

 

in与=的区别

select name from student where name in('zhang','wang','li');

select name from student where name='zhang' or name='li' or name='wang';

的结果是相同

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值