SQL中in和exists的异同

 

-- 学生表
CREATE
TABLE t_student ( id BIGINT PRIMARY KEY, name VARCHAR(255), gender VARCHAR(255), age INT, address VARCHAR(255), INDEX idx_age (age) );
-- 分数表
CREATE TABLE t_stu_score ( stu_id BIGINT, course VARCHAR(255), score INT(255), INDEX idx_userid_course (user_id, course), INDEX idx_score (score), UNIQUE INDEX uk_userid_course (user_id, course) );

 

 

in和exists有什么异同点?

相同点:in和exists都可以作为where的条件,用于子查询

 

exists用法:

select a.* from A a where exists(select 1 from B b where a.id=b.id);

select
stu.* from t_student stu where exists (select stu_score.* from t_stu_score stu_score where stu_score.stu_id = stu.id)

说明:                  A表是主查询的表,B表是子查询的表, A表驱动B表,exists的作用是检查子查询是否有返回结果,如果有,主查询中指定的列。如果子查询返回空集,则主查询将返回空集。

执行先后和次数:先执行一次主查询(有a条结果),并将结果放在内存,然后执行a次子查询,共a+1次数据库交互

命中索引情况:   子查询可以命中索引,主查询不走索引

适用的情况:       A表能命中的记录少,B表能命中的记录多

 

in用法:

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

select stu.* from t_student stu where stu.id in (select stu_score.stu_id from t_stu_score stu_score)

说明:                   A表是主查询的表,B表是子查询的表, B表驱动A表,先查出子查询的结果集,在执行多次主查询,判断主表的字段是否存在于子查询的返回结果集里

执行先后和次数: 先执行子查询(有b条结果),并将结果放在内存,后针对b个结果,执行b次主查询,共b+1次数据库交互

命中索引情况:    主查询和子查询都可以走索引

适用情况:            A表能命中的记录多,B表能命中的记录少,in还可以固定几个值

 

怎么选:

子查询结果集小选in,主查询结果集小选exists,差不多大小再结合索引来看
小表驱动大表(结果集小的驱动结果集大的)
IN查询在主查询表和子查询表上都可以命中索引
Exists查询只能在子查询表上命中索引


not exists和not in的比较

not exists能对子查询走索引

not in (通常)主查询和子查询都不能走索引

结论:子查询基本上选择not exists

 

 常用的一种写法,从多表查询出结果

select a.*, b.* from A a, B b where a.id = b.id  等价于使用inner join

 

left join :左连接  A为主,B为辅

 

 

right join:右连接 B为主,A为辅

 

inner join:内连接,A与B

 

full join:全连接,A或B

 

 

 

full join:两个查询的列合并

union:两个查询的行合并,去重

union all:两个查询的行合并,不去重

 

 
posted @ 2024-03-20 12:44  坏男银  阅读(20)  评论(0编辑  收藏  举报