ITPub博客

首页 > 数据库 > Oracle > Oracle Outer Join里on和where区别详解

Oracle Outer Join里on和where区别详解

原创 Oracle 作者:dingjun123 时间:2026-05-14 22:23:01 0 删除 编辑

oracle  outer join on和where执行顺序:

外连接是以主表数据为基准的,从表没有匹配ON条件的则从表列都置NULL,如果从表有WHERE条件但是不是XX IS NULL或XX(+) IS NULL的,

是正常的不带+的条件,则外连接转为内连接。

ON是外连接关联条件,WHERE是主表过滤或访问条件,主表是先执行WHERE,然后执行ON,

WHERE里也可以增加从表列 IS NULL,从表列IS NULL 这个是外连接后过滤的,从表是先执行ON再执行XX IS NULL。


从表ON里有过滤条件的,也可以先执行,相当于写成inline view,然后执行外连接


 1.where条件如果是主表的条件,则主表先过滤,on从表有过滤条件的实际上也可以先过滤,然后再外连接关联

select *

from t1 left join t2

on t1.object_id=t2.object_id and t2.object_name like 'T%'

where t1.object_id<1000;


Elapsed: 00:00:00.04


Execution Plan

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

Plan hash value: 2122192450


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

| Id  | Operation                            | Name             | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT                     |                  |   897 |   218K|    36   (6)| 00:00:01 |

|*  1 |  HASH JOIN RIGHT OUTER               |                  |   897 |   218K|    36   (6)| 00:00:01 |

|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| T2               |    11 |  1287 |    10  (20)| 00:00:01 |

|   3 |    BITMAP CONVERSION TO ROWIDS       |                  |       |       |            |          |

|   4 |     BITMAP AND                       |                  |       |       |            |          |

|   5 |      BITMAP CONVERSION FROM ROWIDS   |                  |       |       |            |          |

|   6 |       SORT ORDER BY                  |                  |       |       |            |          |

|*  7 |        INDEX RANGE SCAN              | IDX122           |   992 |       |     2   (0)| 00:00:01 |

|   8 |      BITMAP CONVERSION FROM ROWIDS   |                  |       |       |            |          |

|   9 |       SORT ORDER BY                  |                  |       |       |            |          |

|* 10 |        INDEX RANGE SCAN              | IDX_T2_OBJECT_ID |   992 |       |     3   (0)| 00:00:01 |

|  11 |   TABLE ACCESS BY INDEX ROWID BATCHED| T1               |   897 |   115K|    26   (0)| 00:00:01 |

|* 12 |    INDEX RANGE SCAN                  | IDX_T1_OBJECT_ID |   897 |       |     5   (0)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


   1 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID"(+))

   7 - access("T2"."OBJECT_NAME"(+) LIKE 'T%')

       filter("T2"."OBJECT_NAME"(+) LIKE 'T%' AND "T2"."OBJECT_NAME"(+) LIKE 'T%')

  10 - access("T2"."OBJECT_ID"(+)<1000)

       filter("T2"."OBJECT_ID"(+)<1000)

  12 - access("T1"."OBJECT_ID"<1000)



Statistics

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

          1  recursive calls

          0  db block gets

        171  consistent gets

          0  physical reads

          0  redo size

      72358  bytes sent via SQL*Net to client

       1199  bytes received via SQL*Net from client

         68  SQL*Net roundtrips to/from client

          2  sorts (memory)

          0  sorts (disk)

        995  rows processed



等价改写为:从表过滤条件可以相当于inline view,然后on里只保存join条件

select *

from t1 left join (select t2.* from t2 where t2.object_name like 'T%') t22

on t1.object_id=t22.object_id  

where t1.object_id<1000;




2. ON里面有主表过滤条件则比较复杂,因为主表还是按where条件过滤的,这样on里主表过滤条件实际上是完全的

外连接匹配条件,和on里从表过滤条件可以改为inline view不同,主表在on里有过滤条件改不了inline view,

实际上等价于


select *

from t1 left join t2

on t1.object_id=t2.object_id and t1.object_name like 'T%'

;



Elapsed: 00:00:01.88


Execution Plan

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

Plan hash value: 312430291


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

| Id  | Operation             | Name | Rows  | Bytes | Cost (%CPU)| Time     |

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

|   0 | SELECT STATEMENT      |      | 73745 |    17M|   867   (1)| 00:00:01 |

|*  1 |  HASH JOIN RIGHT OUTER|      | 73745 |    17M|   867   (1)| 00:00:01 |

|   2 |   TABLE ACCESS FULL   | T2   |  9999 |  1142K|    69   (2)| 00:00:01 |

|   3 |   TABLE ACCESS FULL   | T1   | 73745 |  9506K|   798   (1)| 00:00:01 |

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


Predicate Information (identified by operation id):

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


   1 - access("T1"."OBJECT_ID"="T2"."OBJECT_ID"(+))

       filter("T1"."OBJECT_NAME" LIKE CASE  WHEN ("T2"."OBJECT_ID"(+)

              IS NOT NULL) THEN 'T%' ELSE 'T%' END )



Statistics

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

         28  recursive calls

          0  db block gets

       7989  consistent gets

       3045  physical reads

          0  redo size

    5136624  bytes sent via SQL*Net to client

      54526  bytes received via SQL*Net from client

       4918  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

      73741  rows processed

      

      

-- on里有主表过滤条件

select *

from t1 left join t2

on t1.object_id=t2.object_id and t1.object_name ='T1'

;


等价于

select * from t1, t2

where ("T1"."OBJECT_ID"="T2"."OBJECT_ID"(+) AND

              "T1"."OBJECT_NAME"=CASE  WHEN ("T2"."OBJECT_ID"(+) IS NOT NULL) THEN

              'T1' ELSE 'T1' END );




来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/7655508/viewspace-3117890/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2008-05-07

  • 博文量
    45
  • 访问量
    90562