標籤:
博文來源(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 Awhere 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 awhere 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效率差不多,可任選一個使用.
oracle中的exists 和not exists 用法 in與exists語句的效率問題