欢迎投稿

今日深度:

SQL之 exists 、in,sqlexistsin

SQL之 exists 、in,sqlexistsin


tips : 
1.外表为大表,内表为小表时,使用exist 
2.外表为小表,内表为大表时,使用in


示例:外表大,内表小
create table outTable (id1 int);
insert into outtable select generate_series(1,1000000);


create table inTable (id1 int);
insert into inTable values(1),(10000),(100000),(1000000);


test=# explain select count(*) from outtable big where exists (select id1 from inTable small  where small.id1=big.id1);  
                                       QUERY PLAN                                        
-----------------------------------------------------------------------------------------
 Aggregate  (cost=18968.50..18968.51 rows=1 width=0)
   ->  Hash Join  (cost=44.50..17718.50 rows=500000 width=0)
         Hash Cond: (big.id1 = small.id1)
         ->  Seq Scan on outtable big  (cost=0.00..13922.00 rows=1000000 width=4)
         ->  Hash  (cost=42.00..42.00 rows=200 width=4)
               ->  HashAggregate  (cost=40.00..42.00 rows=200 width=4)
                     ->  Seq Scan on intable small  (cost=0.00..34.00 rows=2400 width=4)
(7 rows)


Time: 3.743 ms
test=# explain select count(*) from outtable big where id1  in  (select id1 from inTable small  where small.id1=big.id1);
                                  QUERY PLAN                                  
------------------------------------------------------------------------------
 Aggregate  (cost=20032672.00..20032672.01 rows=1 width=0)
   ->  Seq Scan on outtable big  (cost=0.00..20031422.00 rows=500000 width=0)
         Filter: (SubPlan 1)
         SubPlan 1
           ->  Seq Scan on intable small  (cost=0.00..40.00 rows=12 width=4)
                 Filter: (id1 = big.id1)
(6 rows)


Time: 1.286 ms
test=# select count(*) from outtable big where exists (select id1 from inTable small  where small.id1=big.id1);          
 count 
-------
     4
(1 row)


Time: 272.027 ms
test=# select count(*) from outtable big where id1  in  (select id1 from inTable small  where small.id1=big.id1);        
 count 
-------
     4
(1 row)


Time: 4021.244 ms




外表小,内表大
test=# select count(*) from intable small where exists (select id1 from outtable big  where big.id1=small.id1);       
 count 
-------
     4
(1 row)


Time: 4792.643 ms
test=# select count(*) from intable small where id1 in  (select id1 from outtable big  where big.id1=small.id1);         
 count 
-------
     4
(1 row)


Time: 223.778 ms
test=# explain select count(*) from intable small where exists (select id1 from outtable big  where big.id1=small.id1);   
                                       QUERY PLAN                                       
----------------------------------------------------------------------------------------
 Aggregate  (cost=33336.10..33336.11 rows=1 width=0)
   ->  Hash Semi Join  (cost=29840.00..33333.10 rows=1200 width=0)
         Hash Cond: (small.id1 = big.id1)
         ->  Seq Scan on intable small  (cost=0.00..34.00 rows=2400 width=4)
         ->  Hash  (cost=13922.00..13922.00 rows=1000000 width=4)
               ->  Seq Scan on outtable big  (cost=0.00..13922.00 rows=1000000 width=4)
(6 rows)


Time: 1.021 ms
test=# explain select count(*) from intable small where id1 in  (select id1 from outtable big  where big.id1=small.id1);         
                                  QUERY PLAN                                  
------------------------------------------------------------------------------
 Aggregate  (cost=19706446.00..19706446.01 rows=1 width=0)
   ->  Seq Scan on intable small  (cost=0.00..19706443.00 rows=1200 width=0)
         Filter: (SubPlan 1)
         SubPlan 1
           ->  Seq Scan on outtable big  (cost=0.00..16422.00 rows=1 width=4)
                 Filter: (id1 = small.id1)
(6 rows)


Time: 3.578 ms




1、exists 与 in 的区别
可以看出,in是一个集合运算符, a in {a1,a2,a3} 
in前面是一个元素,后面是一个集合,就是判断元素是否在集合里面,是则成立。
从上面可以看出,id1 in  (select id1 from outtable big  where big.id1=small.id1);      --如果id1 在 in 后面的集合中,则该行算在count(*)中,否则不算在count(*)中。


而exists 则为一个存在判断,如果exists后查询有结果,则为真,否则为假。
看下面的示例:
test=#  select count(*) from outtable big where exists  (select id1 from outtable where big.id1>1);                         
 count  
--------
 999999
(1 row)


Time: 488.649 ms
test=#  select count(*) from outtable big where exists  (select id1 from outtable where id1>1);    
  count  
---------
 1000000
(1 row)


Time: 313.216 ms


为什么结果不同?
    (select id1 from outtable where id1>1) 我们知道,这个是有返回结果的,且对exists前面的count(*) 即表任一行是没有任何影响的,故相当于elect count(*) from outtable big ; 即不存在限制条件。
    (select id1 from outtable where big.id1>1)我们知道,这个是有返回结果的,且exists对前面的语句是存在限制的,那就是big.id1>1 故相当于select count(*) from outtable big where big.id1>1 ;




select * from 表A where exists(select * from 表B where 表B.id=表A.id)
这句相当于
select * from 表A where id in (select id from 表B)
对于表A的每一条数据,都执行select * from 表B where 表B.id=表A.id的存在性判断,如果表B中存在表A当前行相同的id,则exists为真,该行显示,否则不显示。


tips:
    1.通常NOT EXISTS要比NOT IN 要快, 因为NOT EXISTS可以使用结合算法而NOT IN 就不行了,而EXISTS则不如IN快, 因为这时候IN可能更多的使用结合算法.
    2.通常exists 不走索引,而in走索引。


参考
1. http://www.cnblogs.com/a-zx/articles/1749957.html

SQL对于IN与EXISTS的不同?

IN 其实与等于相似,比如in(1,2) 就是 = 1 or = 2的一种简单写法,所以一般在元素少的时候使用IN,如果多的话就用exists

exists的用法跟in不一样,一般都需要和子表进行关联,而且关联时,需要用索引,这样就可以加快速度。

你的SQL语句用NOT EXISTS可以写成
select MC001 from BOMMC WHERE NOT EXISTS (SELECT MD001 FROM BOMMD where BOMMC.MC001 = BOMMD.MD001)
 

sql 中的in 与exists不同

假设如下应用:
两张表——用户表TDefUser(userid,address,phone)和消费表 TAccConsume(userid,time,amount),需要查消费超过5000的用户记录。
用exists:
select * from TDefUser
where exists (select 1 from TAccConsume where TDefUser.userid=TAccConsume.userid and TAccConsume.amount>5000)
用in:
select * from TDefUser
where userid in (select userid from TAccConsume where TAccConsume.amount>5000)

通常情况下采用exists要比in效率高。

exists()后面的子查询被称做相关子查询 他是不返回列表的值的.只是返回一个ture或false的结果(这也是为什么子查询里是"select 1"的原因,换成"select 6"完全一样,当然也可以select字段,但是明显效率低些)
其运行方式是先运行主查询一次 再去子查询里查询与其对应的结果 如果是ture则输出,反之则不输出.再根据主查询中的每一行去子查询里去查询.

in()后面的子查询 是返回结果集的,换句话说执行次序和exists()不一样.子查询先产生结果集,然后主查询再去结果集里去找符合要求的字段列表去.符合要求的输出,反之则不输出.
 

www.htsjk.Com true http://www.htsjk.com/shujukunews/4132.html NewsArticle SQL之 exists 、in,sqlexistsin tips : 1.外表为大表,内表为小表时,使用exist 2.外表为小表,内表为大表时,使用in 示例:外表大,内表小 create table outTable (id1 int); insert into outtable select ge...
评论暂时关闭