In與Exists的區別

2022-08-27 16:48:11 字數 4514 閱讀 4775

這兩個函式是差不多的,但由於優化方案不同,通常not exists要比not in要快,因為not exists可以使用結合演算法二not in就不行了,而exists則不如in快,因為這時候in可能更多的使用結合演算法。

select * from tablea where exists(select * from tableb where tableb.id=tablea.id)

這句相當於:select * from tablea where id in (select id from tableb)

對於表tablea的每一條資料,都執行select * from tableb where tableb.id=tablea.id的存在性判斷,如果表tableb中存在表tablea當前行相同的id,則exists為真,該行顯示,否則不顯示。

-----in 和not in-----

----哪些部門中有雇員工資大於?-----

select * from department where department.deptid=

(select fdeptid from employee where employee.empsalary>7000)

----報錯資訊如下:子查詢返回的值多於乙個........

----msg 512, level 16, state 1, line 1

----subquery returned more than 1 value. this is not permitted when the

----subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.---

----改正:將「=」改為「in」

select * from department where department.deptid in

(select fdeptid from employee where employee.empsalary>7000)

go----not in

select * from department where department.deptid in

(select fdeptid from employee where employee.empsalary>7000)

go-----exists 和not exists-----一般用於if語句的存在檢測

----工資改革,檢查雇員工資,達到以上的,每人提高,否則每人提高-----

/*--採用exists子查詢,進行酌情提公升--*/

select * from employee

goif exists (select * from employee where empsalary>7000)

begin

print '有人工資達到,則每人提高,提高後工資為:'

update employee set empsalary=empsalary+300

select * from employee

endelse

begin

print '無人工資達到,則每人提高,提高後工資為:'

update employee set empsalary=empsalary+500

select * from employee

endgo

----in和exists---

select distinct deptname from department

where exists(select * from employee where empgender=1)

goselect distinct deptname from department

where deptid in(select fdeptid from employee where empgender=1)

go----exists相當於存在量詞:表示集合存在,也就是集合不為空只作用於乙個集合。

----exists p表示p不為空時為真;not exists p表示p為空時,為真。

----in表示乙個標量和醫院關係的關係。s in p表示當s與p中的某個值相等時為真;

----s not in p表示s與p中的每乙個值都不相等時,為真。

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要快。

not in 邏輯上不完全等同於not exists,如果你誤用了not in,小心你的程式存在致命的bug:

請看下面的例子:

create table t1 (c1 number,c2 number);

create table t2 (c1 number,c2 number);

insert into t1 values (1,2);

insert into t1 values (1,3);

insert into t2 values (1,2);

insert into t2 values (1,null);

select * from t1 where c2 not in (select c2 from t2);

no rows found

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

c1 c2

1 3[這裡涉及到資料的null值的處理,因為null代表著無法預知]。

正如所看到的,not in 出現了不期望的結果集,存在邏輯錯誤。如果看一下上述兩個select語句的執行計畫,也會不同。後者使用了hash_aj。

因此,請盡量不要使用not in(它會呼叫子查詢),而盡量使用not exists(它會呼叫關聯子查詢)。如果子查詢中返回的任意一條記錄含有空值,則查詢將不返回任何記錄,正如上面例子所示。

除非子查詢欄位有非空限制,這時可以使用not in ,並且也可以通過提示讓它使用hasg_aj或merge_aj連線

a:  用exists替代in、用not exists替代not in

在許多基於基礎表的查詢中,為了滿足乙個條件,往往需要對另乙個表進行聯接.在這種情況下, 使用exists(或not exists)通常將提高查詢的效率. 在子查詢中,not in子句將執行乙個內部的排序和合併. 無論在哪種情況下,not in都是最低效的 (因為它對子查詢中的表執行了乙個全表遍歷). 為了避免使用not in ,我們可以把它改寫成外連線(outer joins)或not exists.

例子:(高效)select * from emp (基礎表) where empno > 0 and exists (select 『x' from dept where dept.deptno = emp.deptno and loc = 『melb』)

(低效)select * from emp (基礎表) where empno > 0 and deptno in(select deptno from dept where loc = 『melb』)

b:  用exists替換distinct

當提交乙個包含一對多表資訊(比如部門表和雇員表)的查詢時,避免在select子句中使用distinct. 一般可以考慮用exist替換, exists 使查詢更為迅速,因為rdbms核心模組將在子查詢的條件一旦滿足後,立刻返回結果。

例:(低效): select distinct dept_no,dept_name from dept d , emp e where d.dept_no = e.dept_no

(高效): select dept_no,dept_name from dept d where exists ( select 『x' from emp e where e.dept_no = d.dept_no);

採集

採集採集

採集

In與Exists的區別

這兩個函式是差不多的,但由於優化方案不同,通常not exists要比not in要快,因為not exists可以使用結合演算法而not in就不行了,而exists則不如in快,因為這時候in可能更多的使用結合演算法。select from tablea where exists select ...

Exists與In的區別

最近在check專案的資料庫,check到儲存過程,裡面看到儲存過程有用到in 和 exsits.整理下 in 和 exsits 的區別 in 是把外表和內錶做hash join,而exists是對外表做loop,每次loop再對內表進行查詢.如此,exists適合外表結果集很小的情況.其他情況則使...

ORACLE in與exists語句的區別

業務問題大概可以這樣描述,乙個父表,乙個子表,查詢的結果是找到子表中沒有使用父表id的記錄,這種情況估計很多系統都會牽涉得到。讓我們來舉乙個例子 表一 父表 parent 表二 子表 childen 父表儲存父親,子表儲存孩子,然後通過pid和父表關聯,查詢需要的結果是找到尚未有孩子的父親。我們來看...