在sql 中,join /in /exists 都可以用来实现,“查询A表中在(或者不在)B表中的记录”,这种查询,在查询的两个表大小相当的情况下,3种查询方式的执行时间通常是:
exists <= in <= join
当表中字段允许NULL时,not in 的方式最慢;
not exists <= left join <= not in
select * from A where id in(select id from B)
select * from A left join B on A.id = B.id
使用join也可以实现这种功能(“查询A表中在(或者不在)B表中的记录”),但是往往吃力不讨好,因为还需要处理NULL,JOIN的使用场景是连接两个表,而不是判断一个表的记录是否在另一个表中
select * from A where id in(select id from B)
但是,通常情况下,两个表中数据是一个较大,一个较小,这种情况下,
in适合子查询表B 数据小的情况;
exists适合子查询表B 数据大的情况
原因:in在查询的时候,先查子查询的表B,然后将内表和外表做一个笛卡尔积,然后按照条件筛选,所以子查询表比较小的时候,in的速度较快;
而exists 是对外表A做loop循环,每次loop循环再对内表B进行查询,即我们先查询的不是子查询B的内容,而是查我们的主查询的表A,所以子查询表数据比较大的时候,exists的速度较快
select * from A where id not in(select id from B)
无论哪个表大,not exists 总是比 not in 执行效率高
原因:not in没有用到索引,同时,内外表都要进行全表扫描;
而 exists的子查询依然可以使用索引。
如下面的表table:
Id Name Class Count Date
1 苹果 水果 10 2011-7-1
1 桔子 水果 20 2011-7-2
1 香蕉 水果 15 2011-7-3
2 白菜 蔬菜 12 2011-7-1
2 青菜 蔬菜 19 2011-7-2
如果想要得到下面的结果:(Id唯一,Date选最近的一次)
1 香蕉 水果 15 2011-7-3
2 青菜 蔬菜 19 2011-7-2
有三种sql可以达到
方法一:
select Id,Name,Class,Count,Date
from Fruit as f
where not exists (select Id,Name,Class,Count,Date
from Fruit
where Id=f.Id and Date>f.Date)
方法儿:配合视图
create view NewFruit as
select Id,MAX(Date) as NewDate
from Fruit as f
group by Id
select Id,Name,Class,Count,Date
from Fruit as f
where exists (select 1 from NewFruit where NewFruit.NewDate=f.Date and NewFruit.Id=f.Id)
方法三:
select Fruit.Id,Name,Class,Count,Date
from Fruit right join (select Id,MAX(Date) as newDate
from Fruit
group by id ) as newf
on Fruit.Date = newf.newDate and Fruit.Id=newf.Id
三种sql的执行效率还没高明白,我自己查看执行时间,估计是数据表太小了,查询的时间都是0。希望大佬能够赐教。