zoukankan      html  css  js  c++  java
  • SQL语句之on子句过滤和where子句过滤区别

    1、测试数据:

    SQL> select * from dept;
     
    DEPTNO DNAME          LOC
    ------ -------------- -------------
         10 ACCOUNTING     NEW YORK
         20 RESEARCH       DALLAS
         30 SALES          CHICAGO
         40 OPERATIONS     BOSTON
     
    SQL> select * from emp;
     
    EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO
    ----- ---------- --------- ----- ----------- --------- --------- ------
      7369 SMITH      CLERK      7902 1980/12/17     800.00               20
      7499 ALLEN      SALESMAN   7698 1981/2/20     1600.00    300.00     30
      7521 WARD       SALESMAN   7698 1981/2/22     1250.00    500.00     30
      7566 JONES      MANAGER    7839 1981/4/2      2975.00               20
      7654 MARTIN     SALESMAN   7698 1981/9/28     1250.00   1400.00     30
      7698 BLAKE      MANAGER    7839 1981/5/1      2850.00               30
      7782 CLARK      MANAGER    7839 1981/6/9      2450.00               10
      7788 SCOTT      ANALYST    7566 1987/4/19     3000.00               20
      7839 KING       PRESIDENT       1981/11/17    5000.00               10
      7844 TURNER     SALESMAN   7698 1981/9/8      1500.00      0.00     30
      7876 ADAMS      CLERK      7788 1987/5/23     1100.00               20
      7900 JAMES      CLERK      7698 1981/12/3      950.00               30
      7902 FORD       ANALYST    7566 1981/12/3     3000.00               20
      7934 MILLER     CLERK      7782 1982/1/23     1300.00               10
     
    14 rows selected

    2、左连接测试

    SQL> select
    e.empno, e.ename, e.deptno, d.deptno, d.dname
       3  from scott.emp e left join scott.dept d on e.deptno = d.deptno and e.deptno != 20 and d.deptno != 30;

         EMPNO ENAME                  DEPTNO     DEPTNO DNAME
    ---------- ------------------------------ ---------- ---------- ------------------------------------------
           7934 MILLER                  10         10 ACCOUNTING
           7839 KING                   10         10 ACCOUNTING
           7782 CLARK                  10         10 ACCOUNTING
           7900 JAMES                  30
           7844 TURNER                  30
           7698 BLAKE                  30
           7654 MARTIN                  30
           7521 WARD                   30
           7499 ALLEN                  30
           7902 FORD                   20
           7876 ADAMS                  20
           7788 SCOTT                  20
           7566 JONES                  20
           7369 SMITH                  20

    14 rows selected.


    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 3387915970

    ---------------------------------------------------------------------------
    | Id  | Operation       | Name | Rows  | Bytes | Cost (%CPU)| Time      |
    ---------------------------------------------------------------------------
    |   0 | SELECT STATEMENT   |      |    14 |   364 |    7  (15)| 00:00:01 |
    |*  1 |  HASH JOIN OUTER   |      |    14 |   364 |    7  (15)| 00:00:01 |
    |   2 |   TABLE ACCESS FULL| EMP  |    14 |   182 |    3   (0)| 00:00:01 |
    |*  3 |   TABLE ACCESS FULL| DEPT |    3 |    39 |    3   (0)| 00:00:01 |
    ---------------------------------------------------------------------------

    Predicate Information (identified by operation id):
    ---------------------------------------------------

       1 - access("E"."DEPTNO"="D"."DEPTNO"(+))
            filter("E"."DEPTNO"<>CASE  WHEN ("D"."DEPTNO"(+) IS NOT NULL)
               THEN 20 ELSE 20 END )
        3 - filter("D"."DEPTNO"(+)<>30)


    Statistics
    ----------------------------------------------------------
           0  recursive calls
           0  db block gets
          13  consistent gets
           0  physical reads
           0  redo size
            1082  bytes sent via SQL*Net to client
         524  bytes received via SQL*Net from client
           2  SQL*Net roundtrips to/from client
           0  sorts (memory)
           0  sorts (disk)
          14  rows processed

        
    -- 结论:left join 仅有on子句
    -- 过滤条件对左表无效;

    -- on子句过滤条件仅对右表生效;
    -- 对于右表,过滤条件在连接之前生效(即先过滤,后连接);
    -- 对于左表,过滤条件在连接之后生效(即先连接,后过滤)。
         
    SQL> select
    e.empno, e.ename, e.deptno, d.deptno, d.dname
       3  from scott.emp e left join scott.dept d on e.deptno = d.deptno where e.deptno != 20 and d.deptno != 30;

         EMPNO ENAME                  DEPTNO     DEPTNO DNAME
    ---------- ------------------------------ ---------- ---------- ------------------------------------------
           7782 CLARK                  10         10 ACCOUNTING
           7934 MILLER                  10         10 ACCOUNTING
           7839 KING                   10         10 ACCOUNTING


    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 844388907

    ----------------------------------------------------------------------------------------
    | Id  | Operation             | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
    ----------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT         |           |     9 |   234 |     6    (17)| 00:00:01 |
    |   1 |  MERGE JOIN             |           |     9 |   234 |     6    (17)| 00:00:01 |
    |   2 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     3 |    39 |     2     (0)| 00:00:01 |
    |*  3 |    INDEX FULL SCAN         | PK_DEPT |     3 |       |     1     (0)| 00:00:01 |
    |*  4 |   SORT JOIN             |           |     9 |   117 |     4    (25)| 00:00:01 |
    |*  5 |    TABLE ACCESS FULL         | EMP     |     9 |   117 |     3     (0)| 00:00:01 |
    ----------------------------------------------------------------------------------------

    Predicate Information (identified by operation id):
    ---------------------------------------------------

       3 - filter("D"."DEPTNO"<>30 AND "D"."DEPTNO"<>20)
        4 - access("E"."DEPTNO"="D"."DEPTNO")
            filter("E"."DEPTNO"="D"."DEPTNO")
        5 - filter("E"."DEPTNO"<>20 AND "E"."DEPTNO"<>30)


    Statistics
    ----------------------------------------------------------
           0  recursive calls
           0  db block gets
          10  consistent gets
           0  physical reads
           0  redo size
         916  bytes sent via SQL*Net to client
         524  bytes received via SQL*Net from client
           2  SQL*Net roundtrips to/from client
           1  sorts (memory)
           0  sorts (disk)
           3  rows processed

    -- 结论:where子句过滤
    -- 过滤条件对于左右表都有效;
    -- 对于右表,过滤条件在连接之前生效(即先过滤,后连接);
    -- 对于左表,过滤条件在连接之前生效(即先过滤,后连接);
    -- 对于左连接,右表过滤字段出现在连接条件中,左连解会变成内连接。

    3、以下SQL自行测试,可验证以上结论:

    select
    e.empno, e.ename, e.deptno, d.deptno, d.dname
    from scott.dept d join scott.emp e on e.deptno = d.deptno where e.deptno != 20 and d.deptno != 30;
      
    select
    e.empno, e.ename, e.deptno, d.deptno, d.dname
    from scott.dept d join scott.emp e on e.deptno = d.deptno where d.deptno != 30;
      
    select
    e.empno, e.ename, e.deptno, d.deptno, d.dname
    from scott.dept d join scott.emp e on e.deptno = d.deptno where e.deptno != 20;


    select
    e.empno, e.ename, e.deptno, d.deptno, d.dname
    from scott.dept d left join scott.emp e on e.deptno = d.deptno where e.deptno != 20 and d.deptno != 30;
      
    select
    e.empno, e.ename, e.deptno, d.deptno, d.dname
    from scott.dept d left join scott.emp e on e.deptno = d.deptno where d.deptno != 30;
      
    select
    e.empno, e.ename, e.deptno, d.deptno, d.dname
    from scott.dept d left join scott.emp e on e.deptno = d.deptno where e.deptno != 20;

  • 相关阅读:
    jquery 菜单1
    Notepad++在vs2008下编译运行
    Linux readelf命令的使用
    Linux下truss、strace或ltrace的使用
    (转载)new和malloc的区别
    windows xp 设置回环网卡
    Linux下没有网线的情况下,从主机使用SSH登录虚拟机
    Linux ELF文件学习(1)
    C++子类继承父类
    (转载)wireshark抓包的时候有黄条、蓝条各代表什么意思?
  • 原文地址:https://www.cnblogs.com/wcwen1990/p/8486546.html
Copyright © 2011-2022 走看看