程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle教程 >> oracle中的exists 和not exists 用法 in與exists語句的效率問題,oracleexists

oracle中的exists 和not exists 用法 in與exists語句的效率問題,oracleexists

編輯:Oracle教程

oracle中的exists 和not exists 用法 in與exists語句的效率問題,oracleexists


博文來源(oracle中的exists 和not exists 用法):http://chenshuai365-163-com.iteye.com/blog/1003247

博文來源(  in與exists語句的效率問題):http://www.cnblogs.com/iceword/archive/2011/02/15/1955337.html

(一)

exists (sql 返回結果集為真)
not exists (sql 不返回結果集為真)
如下:
表A
ID NAME

1    A1
2    A2
3  A3

表B
ID AID NAME
1    1 B1
2    2 B2
3    2 B3

表A和表B是1對多的關系 A.ID => B.AID

 1 SELECT ID,NAME FROM A WHERE EXIST (SELECT * FROM B WHERE A.ID=B.AID)
 2 執行結果為
 3 1 A1
 4 2 A2
 5 原因可以按照如下分析
 6 SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=1)
 7 --->SELECT * FROM B WHERE B.AID=1有值返回真所以有數據
 8 
 9 SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=2)
10 --->SELECT * FROM B WHERE B.AID=2有值返回真所以有數據
11 
12 SELECT ID,NAME FROM A WHERE EXISTS (SELECT * FROM B WHERE B.AID=3)
13 --->SELECT * FROM B WHERE B.AID=3無值返回真所以沒有數據
14 
15 NOT EXISTS 就是反過來
16 SELECT ID,NAME FROM A WHERE NOT EXIST (SELECT * FROM B WHERE A.ID=B.AID)
17 執行結果為
18 3 A3 

 


(二)SQL中IN,NOT IN,EXISTS,NOT EXISTS的用法和差別:

 

  IN 關鍵字使您得以選擇與列表中的任意一個值匹配的行。確定給定的值是否與子查詢或列表中的值相匹配。

  (1)獲得居住在 California、Indiana 或 Maryland 州的所有作者的姓名和州的列表時,就需要下列查詢:
  SELECT ProductID, ProductName FROM Northwind.dbo.Products WHERE CategoryID = 1 OR CategoryID = 4 OR CategoryID = 5
  然而,如果使用 IN,少鍵入一些字符也可以得到同樣的結果:
  SELECT ProductID, ProductName FROM Northwind.dbo.Products WHERE CategoryID IN (1, 4, 5)
  IN 關鍵字之後的項目必須用逗號隔開,並且括在括號中。


  (2)下列查詢在 titleauthor 表中查找在任一種書中得到的版稅少於 50% 的所有作者的 au_id,然後從 authors 表中選擇 au_id 與titleauthor 查詢結果匹配的所有作者的姓名:
  SELECT au_lname, au_fname FROM authors WHERE au_id IN (SELECT au_id FROM titleauthor WHERE royaltyper <50)

  結果顯示有一些作者屬於少於 50% 的一類。
  NOT IN:通過 NOT IN 關鍵字引入的子查詢也返回一列零值或更多值。
  以下查詢查找沒有出版過商業書籍的出版商的名稱。
  SELECT pub_name FROM publishers WHERE pub_id NOT IN (SELECT pub_id FROM titles WHERE type = 'business')

  使用 EXISTS 和 NOT EXISTS 引入的子查詢可用於兩種集合原理的操作:交集與差集。
     (1) 兩個集合的交集包含同時屬於兩個原集合的所有元素。
    (2)差集包含只屬於兩個集合中的第一個集合的元素。
    EXISTS:指定一個子查詢,檢測行的存在。
  本示例所示查詢查找由位於以字母 B 開頭的城市中的任一出版商出版的書名:
  SELECT DISTINCT pub_name FROM publishers WHERE EXISTS (SELECT * FROM titles WHERE pub_id = publishers.pub_id AND type ='business')
  SELECT distinct pub_name FROM publishers WHERE pub_id IN (SELECT pub_id FROM titles WHERE type = 'business')
  兩者的區別:   EXISTS:後面可以是整句的查詢語句如:SELECT * FROM titles   IN:後面只能是對單列:SELECT pub_id FROM titles   NOT EXISTS:   例如,要查找不出版商業書籍的出版商的名稱:   SELECT pub_name FROM publishers WHERE NOT EXISTS (SELECT * FROM titles WHERE pub_id = publishers.pub_id AND type =   'business')   下面的查詢查找已經不銷售的書的名稱:   SELECT title FROM titles WHERE NOT EXISTS (SELECT title_id FROM sales WHERE title_id = titles.title_id)

 

(三)In 於 EXISTS 的效率問題

select * from A
where id in(select id from B)

以上查詢使用了in語句,in()只執行一次,它查出B表中的所有id字段並緩存起來.之後,檢查A表的id是否與B表中的id相等,如果相等則將A表的記錄加入結果集中,直到遍歷完A表的所有記錄.
它的查詢過程類似於以下過程

List resultSet=[];
Array A=(select * from A);
Array B=(select id from B);

for(int i=0;i<A.length;i++) {
   for(int j=0;j<B.length;j++) {
      if(A[i].id==B[j].id) {
         resultSet.add(A[i]);
         break;
      }
   }
}
return resultSet;

可以看出,當B表數據較大時不適合使用in(),因為它會B表數據全部遍歷一次.
如:A表有10000條記錄,B表有1000000條記錄,那麼最多有可能遍歷10000*1000000次,效率很差.
再如:A表有10000條記錄,B表有100條記錄,那麼最多有可能遍歷10000*100次,遍歷次數大大減少,效率大大提升.

結論:in()適合B表比A表數據小的情況

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

以上查詢使用了exists語句,exists()會執行A.length次,它並不緩存exists()結果集,因為exists()結果集的內容並不重要,重要的是結果集中是否有記錄,如果有則返回true,沒有則返回false.
它的查詢過程類似於以下過程

List resultSet=[];
Array A=(select * from A)

for(int i=0;i<A.length;i++) {
   if(exists(A[i].id) {    //執行select 1 from B b where b.id=a.id是否有記錄返回
       resultSet.add(A[i]);
   }
}
return resultSet;

當B表比A表數據大時適合使用exists(),因為它沒有那麼遍歷操作,只需要再執行一次查詢就行.
如:A表有10000條記錄,B表有1000000條記錄,那麼exists()會執行10000次去判斷A表中的id是否與B表中的id相等.
如:A表有10000條記錄,B表有100000000條記錄,那麼exists()還是執行10000次,因為它只執行A.length次,可見B表數據越多,越適合exists()發揮效果.
再如:A表有10000條記錄,B表有100條記錄,那麼exists()還是執行10000次,還不如使用in()遍歷10000*100次,因為in()是在內存裡遍歷比較,而exists()需要查詢數據庫,我們都知道查詢數據庫所消耗的性能更高,而內存比較很快.

結論:exists()適合B表比A表數據大的情況

當A表數據與B表數據一樣大時,in與exists效率差不多,可任選一個使用.

 



 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved