Oracle exists和in區別比較

2021-06-29 17:00:36 字數 3504 閱讀 2548

有兩個簡單例子,以說明 「exists」和「in」的效率問題

1) select * from t1 where exists(select 1 from t2 where t1.a=t2.a) ;

t1資料量小而t2資料量非常大時,t1<2) select * from t1 where t1.a in (select t2.a from t2) ;

t1資料量非常大而t2資料量小時,t1>>t2 時,2) 的查詢效率高。

exists 用法:

請注意 1)句中的有顏色字型的部分 ,理解其含義;

其中 「select 1 from t2 where t1.a=t2.a」 相當於乙個關聯表查詢,相當於

「select 1 from t1,t2 where t1.a=t2.a」

但是,如果你噹噹執行 1) 句括號裡的語句,是會報語法錯誤的,這也是使用exists需要注意的地方。

「exists(***)」就表示括號裡的語句能不能查出記錄,它要查的記錄是否存在。

因此「select 1」這裡的 「1」其實是無關緊要的,換成「*」也沒問題,它只在乎括號裡的資料能不能查詢出來,是否存在這樣的記錄,如果存在,這 1) 句的where 條件成立。

in 的用法:

繼續引用上面的例子

「2) select * from t1 where t1.a in (select t2.a from t2) 」

這裡的「in」後面括號裡的語句搜尋出來的字段的內容一定要相對應,一般來說,t1和t2這兩個表的a欄位表達的意義應該是一樣的,否則這樣查沒什麼意義。

打個比方:t1,t2表都有乙個字段,表示工單號,但是t1表示工單號的欄位名叫「ticketid」,t2則為「id」,但是其表達的意義是一樣的,而且資料格式也是一樣的。這時,用 2)的寫法就可以這樣:

「select * from t1 where t1.ticketid in (select t2.id from t2) 」

select name from employee where name not in (select name from student);

select name from employee where not exists (select name from student);

第一句sql語句的執行效率不如第二句。

通過使用exists,oracle會首先檢查主查詢,然後執行子查詢直到它找到第乙個匹配項,這就節省了時間。oracle在執行in子查詢時,首先執行子查詢,並將獲得的結果列表存放在乙個加了索引的臨時表中。在執行子查詢之前,系統先將主查詢掛起,待子查詢執行完畢,存放在臨時表中以後再執行主查詢。這也就是使用exists比使用in通常查詢速度快的原因

假設如下應用:

兩張表——使用者表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()不一樣.子查詢先產生結果集,然後主查詢再去結果集裡去找符合要求的字段列表去.符合要求的輸出,反之則不輸出.

比如使用者表tdefuser(userid,address,phone),消費表 taccconsume(userid,time,amount)資料如下:

消費表聚集索引是userid,time

資料(注意因為有聚集索引,實際儲存也是按以下次序的)

1   2006-1-1  200

1   2006-1-2  300

1   2006-1-2  500

1   2006-1-3  2000

1   2006-1-3  2000

1   2006-1-4  400

1   2006-1-5  500

2   2006-1-1  200

2   2006-1-2  300

2   2006-1-2  500

2   2006-1-3  2000

2   2006-1-3  6000

2   2006-1-4  400

2   2006-1-5  8000

3   2006-1-1  7000

3   2006-1-2  30000

3   2006-1-2  50000

3   2006-1-3  20000

語句:select * from tdefuser

where exists (select 1 from taccconsume where tdefuser.userid=taccconsume.userid and taccconsume.amount>5000)

對於userid=1,需要找所有記錄,才返回false,與第二個語句的效率差不多

對於userid=2,找到2006-1-3的記錄,就返回true,比第而箇語句的效率高

對於userid=3,第一條記錄就返回true,比第二個語句的效率高

語句select * from tdefuser

where userid in (select userid from taccconsume where taccconsume.amount>5000)

返回空記錄集22

3333

再判斷語句

select * from tdefuser

where userid in (select userid from taccconsume where userid=tdefuser.userid and amount>5000)

對於userid=1,需要找所有記錄,返回空記錄集,比較判斷

對於userid=2,需要找所有記錄,返回記錄集22

,比較判斷

對於userid=3需要找所有記錄,返回記錄集33

33,比較判斷

表中如果沒有聚集索引,對exists每個userid查詢的條數都不同,但都是<=第三個語句需要掃瞄的條數,極端的(比如》 5000的都是在最後)與第三個語句效率相似,一般的比第二個語句快,所以說「一般」exists比in效率高。

oracle exists 和 in 效率問題

有兩個簡單例子,以說明 exists 和 in 的效率問題 1 select from t1 where exists select 1 from t2 where t1.a t2.a t1資料量小而t2資料量非常大時,t1 2 select from t1 where t1.a in select...

oracle EXISTS語句用法

比如 a,b 關聯列為 a.id b.id,現在要取 a 中的資料,其中id在b中也存在 select from a where exists select 1 from b where a.id b.id 或者 現在要取 a 中的資料,其中id在b中 不存在 select from a where...

Oracle exists用法,查詢相同或相似資料

sql中經常遇到如下情況,在一張表中有兩條記錄基本完全一樣,某個或某幾個欄位有些許差別,這時候可能需要我們踢出這些有差別的資料,即兩條或多條記錄中只保留一項。如下 表timeand 針對time欄位相同時有不同total和name的情形,每當遇到相同的則只取其中一條資料,最簡單的實現方法有兩種 1 ...