In與Exists的區別

這兩個函數是差很少的,但因爲優化方案不一樣,一般NOT Exists要比NOT IN要快,由於NOT EXISTS可使用結合算法二NOT IN就不行了,而EXISTS則不如IN快,由於這時候IN可能更多的使用結合算法。web

    Select * from tableA Where exists(Select * From tableB Where tableB.ID=tableA.ID)算法

    這句至關於:Select * from tableA Where id in (Select ID From tableB)express

    對於表tableA的每一條數據,都執行Select * From tableB Where tableB.ID=tableA.ID的存在性判斷,若是表tableB中存在表tableA當前行相同的ID,則Exists爲真,該行顯示,不然不顯示。ide

  • IN適合於外表大而內表小的狀況;EXISTS適合於外表小而內表大的狀況
  • In肯定給定的值是否與子查詢或列表中的值相匹配
  • Exists指定一個子查詢,檢測行的存在

-----IN 和NOT IN-----函數

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

 

select * from Department where Department.deptID=優化

(select FDeptID from Employee where Employee.empSalary>7000)url

----報錯信息以下:子查詢返回的值多於一個........spa

----Msg 512, Level 16, State 1, Line 1orm

----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

go

if exists (select * from Employee where empSalary>7000)

begin

    Print '有人工資達到,則每人提升,提升後工資爲:'

    update Employee set empSalary=empSalary+300

    select * from Employee

end

else

begin

    Print '無人工資達到,則每人提升,提升後工資爲:'

    update Employee set empSalary=empSalary+500

    select * from Employee

end

go

 

----IN和Exists---

Select distinct deptName from Department

where exists(select * from Employee where empGender=1)

go

 

Select 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);
相關文章
相關標籤/搜索