在關聯子查詢中in與exists的區別

skyin_1603發表於2016-10-09
in與exists在子查詢中也容易混用,前者表示是否滿足,是否在所確定的範圍,
後者表示是否存在。理解這兩個,還是從null值入手去理解。以下透過一些分解操作
來更深理解這兩個的的用法,順便牽涉一些最佳化的說法。

背景:
1、在表emp中檢視最高領導人員的有關資訊:(操作查詢前開啟sqlplus的計時包:set timing on

1》Not exists:

SQL> select empno,ename,sal,mgr

  2   from emp  outer

  3  where not exists(

  4  select 0 from emp inner

  5  where outer.mgr = inner.mgr);

     EMPNO ENAME             SAL        MGR

---------- ---------- ---------- ----------

      7839 KING             5000

Elapsed: 00:00:00.01


2》Not in

SQL> select empno,ename,sal,mgr

  2   from emp

  3  where mgr not in(

  4   select mgr from emp);

no rows selected

Elapsed: 00:00:00.00

2、以下將上面的子查詢與主查詢分解,分別查詢結果:
1》主查詢

SQL> select empno,ename,sal,mgr

  2  from emp;

     EMPNO ENAME             SAL        MGR

---------- ---------- ---------- ----------

      7369 SMITH             800       7902

      7499 ALLEN            1600       7698

      7521 WARD             1250       7698

      7566 JONES            2975       7839

      7654 MARTIN           1250       7698

      7698 BLAKE            2850       7839

      7782 CLARK            2450       7839

      7788 SCOTT            3000       7566

      7839 KING             5000             

      7844 TURNER           1500       7698

      7876 ADAMS            1100       7788


     EMPNO ENAME             SAL        MGR

---------- ---------- ---------- ----------

      7900 JAMES             950       7698

      7902 FORD             3000       7566

      7934 MILLER           1300       7782

14 rows selected. 



2》子查詢:

SQL>  select mgr from emp;

       MGR

----------

      7902

      7698

      7698

      7839

      7698

      7839

      7839

      7566


      7698

      7788


       MGR

----------

      7698

      7566

      7782

14 rows selected.

發現,子查詢存在為空值null的行。

3》正面查詢:

SQL> select empno,ename,sal,mgr

  2  from emp

  3  where mgr in(

  4  select mgr from emp);

     EMPNO ENAME             SAL        MGR

---------- ---------- ---------- ----------

      7369 SMITH             800       7902

      7900 JAMES             950       7698

      7844 TURNER           1500       7698

      7654 MARTIN           1250       7698

      7521 WARD             1250       7698

      7499 ALLEN            1600       7698

      7782 CLARK            2450       7839

      7698 BLAKE            2850       7839

      7566 JONES            2975       7839

      7902 FORD             3000       7566

      7788 SCOTT            3000       7566


     EMPNO ENAME             SAL        MGR

---------- ---------- ---------- ----------

      7876 ADAMS            1100       7788

      7934 MILLER           1300       7782

13 rows selected.

可以看到,in查詢,只有13行,比上面的14行少了一行,因為 null <> null。

3、比較兩者查詢的時間花費
檢視入職時間為80年員工的資訊:

1》Exists耗時:

SQL> select empno,ename,sal,hiredate

  2  from emp outer

  3  where exists(

  4  select 1 from emp inner

  5  where outer.empno = inner.empno

  6  and substr(hiredate,8,2) ='80');

     EMPNO ENAME             SAL HIREDATE

---------- ---------- ---------- ---------

      7369 SMITH             800 17-DEC-80

Elapsed: 00:00:00.01


2》In耗時:

SQL> select empno,ename,sal,hiredate

  2  from emp outer

  3  where 1 in(

  4  select 1 from emp inner

  5   where outer.empno = inner.empno

  6  and substr(hiredate,8,2) ='80');


     EMPNO ENAME             SAL HIREDATE

---------- ---------- ---------- ---------

      7369 SMITH             800 17-DEC-80

Elapsed: 00:00:00.05


透過上面的兩個方面的測試看出,一個兩者在關聯子查詢時候所表示的條件範圍不一樣,
in表示外部的結果與內部查詢結果匹配,exists表示外部的結果是否存在於內部的查詢結果。
再有,在查詢相同任務的時候,exists耗時大大小於in的耗時。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31392094/viewspace-2125963/,如需轉載,請註明出處,否則將追究法律責任。

相關文章