SQL中IN與EXISTS的比較

IN
確定給定的值是否與子查詢或列表中的值相匹配。

EXISTS
指定一個子查詢,檢測行的存在。

比較使用 EXISTS 和 IN 的查詢

這個例子比較了兩個語義類似的查詢。第一個查詢使用 EXISTS 而第二個查詢使用 IN。注意兩個查詢返回相同的信息。

USE pubs
GO
SELECT DISTINCT pub_name
FROM publishers
WHERE EXISTS
(SELECT *
FROM titles
WHERE pub_id = publishers.pub_id
AND type = 'business')
GO

-- Or, using the IN clause:

USE pubs
GO
SELECT distinct pub_name
FROM publishers
WHERE pub_id IN
(SELECT pub_id
FROM titles
WHERE type = 'business')
GO

下面是任一查詢的結果集:

pub_name
----------------------------------------
Algodata Infosystems
New Moon Books

(2 row(s) affected)
 
exits 相當於存在量詞:表示集合存在,也就是集合不爲空只作用一個集合.例如 exist P 表示P不空時爲真; not exist P表示p爲空時 爲真 in表示一個標量和一元關係的關係。例如:s in P表示當s與P中的某個值相等時 爲真; s not in P 表示s與P中的每一個值都不相等時 爲真
在Oracle SQL中取數據時有時要用到in 和 exists 那麼他們有什麼區別呢?

1 性能上的比較
比如Select * from T1 where x in ( select y from T2 )
執行的過程相當於:
select *
  from t1, ( select distinct y from t2 ) t2
where t1.x = t2.y;

相對的

select * from t1 where exists ( select null from t2 where y = x )
執行的過程相當於:
for x in ( select * from t1 )
   loop
      if ( exists ( select null from t2 where y = x.x )
      then
         OUTPUT THE RECORD
      end if
end loop
表 T1 不可避免的要被完全掃描一遍

分別適用在什麼情況?
以子查詢 ( select y from T2 )爲考慮方向
如果子查詢的結果集很大需要消耗很多時間,但是T1比較小執行( select null from t2 where y = x.x )非常快,那麼exists就比較適合用在這裏
相對應得子查詢的結果集比較小的時候就應該使用in.
in和exists
in 是把外表和內表作hash 連接,而exists是對外表作loop循環,每次loop循環再對內表進行查詢。
一直以來認爲exists比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 extsts 的子查詢依然能用到表上的索引。
所以無論那個表大,用not exists都比not in要快。

in 與 =的區別

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

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

的結果是相同的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章