t1表字段:id、name;t2表字段:id、aId。 t2表aId字段关联的是t1表的id
1、select a.* from t1 a where a.name not in('aaa','bbb'); -- 能筛选出表t1的字段name不等于aaa和bbb的记录
2、select a.* from t1 a where a.name not in('aaa','bbb',null); --不能筛选出任何记录
3、select a.* from t1 a where not exists(select b.* from t2 b where b.aId=a.id); -- 能筛选出表t1的字段name不等于aaa和bbb的记录
总结:
1、exists是对外表做loop循环,每次loop循环再对内表(子查询)进行查询,那么因为对内表的查询使用的索引(内表效率高,故可用大表),而外表有多大都需要遍历,不可避免(尽量用小表),故内表大的使用exists,可加快效率;
in是把外表和内表做hash连接,先查询内表,再把内表结果与外表匹配,对外表使用索引(外表效率高,可用大表),而内表多大都需要查询,不可避免,故外表大的使用in,可加快效率;
结论:外层查询表小于子查询表,则用exists,外层查询表大于子查询表,则用in,如果外层和子查询表差不多,则爱用哪个用哪个。
2、如果用not in (实质相当于:!= and != ···),则是内外表都全表扫描,不使用索引,效率低,可考虑使用not exists。
3、从1和2的sql可以看出,使用not in时需要注意:in中的数据不能为null的。