`
wsql
  • 浏览: 11790602 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

oracle的left join,right join和full join的一点介绍

 
阅读更多

以下是摘自oracle ocp9i文档:
outer join syntax:
1)you use an outer join to also see rows that do not meet the join condition
2)the outer join operator is the plus sign(+)
outer join restrictions:
1)the outer join operator can appear on only one side of the expression:the side that has information missing.it returns those rows from one table that have no direct match in the other table.
2)a condition involving an outer join cannot use the IN operator or be linked to another condition by the OR operator.

配置实验环境:

hr@ORCL> drop table a;
hr@ORCL> drop table b;
hr@ORCL> create table a(id number,name varchar2(10));
hr@ORCL> create table b(id number,name varchar2(10));
hr@ORCL> insert into a values(1,'a');
hr@ORCL> insert into a values(2,'b');
hr@ORCL> insert into a values(3,'c');
hr@ORCL> insert into b values(1,'a');
hr@ORCL> insert into b values(2,'b');
hr@ORCL> insert into b values(4,'d');
hr@ORCL> select * from a;

        ID NAME
---------- ----------
         1 a
         2 b
         3 c

hr@ORCL> select * from b;

        ID NAME
---------- ----------
         1 a
         2 b
         4 d

hr@ORCL> commit;


--全外连接的结果是:
1)选出所有满足条件的结果
2)以左表为准,将左表不满足条件的结果接在左边
3)以右表为准,把右表不满足条件的结果接在右边
4)将以上结果全部合起来

hr@ORCL> select a.id,b.id from a full join b on a.id=b.id;

        ID         ID
---------- ----------
         1          1
         2          2
         3
                    4


--left out join和oracle的加号在右结果是相同。同理,right out join和加号在左是一样的。(sql99的语法和oracle私有语法的比较)

hr@ORCL> select a.id,b.id from a,b where a.id=b.id(+);

        ID         ID
---------- ----------
         1          1
         2          2
         3

hr@ORCL> select a.id,b.id from a left outer join b on a.id=b.id;

        ID         ID
---------- ----------
         1          1
         2          2
         3


--结果类似于from a left join b on a.col=b.col and a.coln=....。单个列选择条件的列是基表(加号在谁身上谁是从表,没有加号的一方是基表)的用decode和+改写,不能用一般的改写,若不是基表的可以简单用+改写。比如:

SQL> SELECT a.ID,b.ID
  2  FROM a FULL JOIN b
  3  ON a.ID=b.ID AND a.NAME='a';

        ID         ID
---------- ----------
         1          1
         2 
         3 
         1          1
                    4
                    2

改写之:

SQL> SELECT a.ID,b.ID
  2  FROM a,b WHERE a.id=decode(a.NAME,'a',b.ID(+))
  3  UNION ALL
  4  SELECT a.ID,b.ID
  5  FROM a,b WHERE a.ID(+)=b.ID AND a.NAME(+)='a' AND a.ID IS NULL;

        ID         ID
---------- ----------
         1          1
         2 
         3 
         1          1
                    2
                    4


用union来实现上面例子的full join结果,需要考虑表的关系。

1)如果是两表1:1
加号在左,以右为准(相当于sql99的right join)
加号在右,以左为准(相当于sql99的left join)

即:在没加号的地方,读取前缀。

比如:where e.department_id(+)=d.department_id

读作:所有部门

hr@ORCL> select a.id,b.id from a,b where a.id=b.id(+)
  2  union
  3      select a.id,b.id from a,b where a.id(+)=b.id;

        ID         ID
---------- ----------
         1          1
         2          2
         3
                    4


2)如果是两表1:n,用union剔重就不正确。

hr@ORCL> insert into a values(1,'a');
hr@ORCL> commit;
hr@ORCL> select * from a;

        ID NAME
---------- ----------
         1 a
         2 b
         3 c
         1 a

hr@ORCL> select * from b;

        ID NAME
---------- ----------
         1 a
         2 b
         4 d
--1:n用UNION不正确
SQL> SELECT a.ID,b.ID
  2  FROM a,b WHERE a.ID=b.ID(+)
  3  UNION
  4  SELECT a.ID,b.ID
  5  FROM a,b WHERE a.ID(+)=b.ID;

        ID         ID
---------- ----------
         1          1
         2          2
         3 
                    4

--正确解法有三。注意,在使用sql时,任何时候,任何地方,一定要考虑null!!!切记。
法一:
SQL> SELECT a.ID,b.ID
  2  FROM a,b WHERE a.ID=b.ID(+)
  3  UNION ALL
  4  SELECT a.ID,b.ID
  5  FROM a,b WHERE a.ID(+)=b.ID AND a.ID IS NULL;

        ID         ID
---------- ----------
         1          1
         1          1
         2          2
         3 
                    4

法二:
SQL> SELECT a.ID,b.ID
  2  FROM a,b WHERE a.ID=b.ID(+) AND b.ID IS NULL
  3  UNION ALL
  4  SELECT a.ID,b.ID
  5  FROM a,b WHERE a.ID(+)=b.ID;

        ID         ID
---------- ----------
         3 
         1          1
         1          1
         2          2
                    4
法三:
SQL> SELECT a.ID,b.ID
  2  FROM a FULL JOIN b
  3  ON a.ID=b.ID;

        ID         ID
---------- ----------
         1          1
         1          1
         2          2
         3 
                    4


--逗号和full join是不一样的。另外,full join须加上关键字on,才是完整的语句。

hr@ORCL> select p.id,t.id from p,t where p.id=t.id;

        ID         ID
---------- ----------
         1          1
         3          3

hr@ORCL> select p.id,t.id from p full join t on p.id=t.id;

        ID         ID
---------- ----------
         1          1
         3          3
         2
                    5


全外连接和union连接都可以实现相同结果。我们来看一下他们的执行计划。

全外连接的执行计划:
hr@ORCL> select a.id,b.id from a full join b on a.id=b.id;

        ID         ID
---------- ----------
         1          1
         2          2
         3
                    4


Execution Plan
----------------------------------------------------------
Plan hash value: 2192011130

-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |     4 |   104 |    13   (8)| 00:00:01 |
|   1 |  VIEW                |      |     4 |   104 |    13   (8)| 00:00:01 |
|   2 |   UNION-ALL          |      |       |       |            |          |
|*  3 |    HASH JOIN OUTER   |      |     3 |   312 |     7  (15)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| A    |     3 |   195 |     3   (0)| 00:00:01 |
|   5 |     TABLE ACCESS FULL| B    |     3 |   117 |     3   (0)| 00:00:01 |
|*  6 |    HASH JOIN ANTI    |      |     1 |    26 |     7  (15)| 00:00:01 |
|   7 |     TABLE ACCESS FULL| B    |     3 |    39 |     3   (0)| 00:00:01 |
|   8 |     TABLE ACCESS FULL| A    |     3 |    39 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------

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

   3 - access("A"."ID"="B"."ID"(+))
   6 - access("A"."ID"="B"."ID")

Note
-----
   - dynamic sampling used for this statement


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

union的执行计划:
hr@ORCL> select a.id,b.id from a,b where a.id=b.id(+)
  2  union
  3      select a.id,b.id from a,b where a.id(+)=b.id;

        ID         ID
---------- ----------
         1          1
         2          2
         3
                    4


Execution Plan
----------------------------------------------------------
Plan hash value: 891669117

-----------------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |     6 |   156 |    15  (60)| 00:00:01 |
|   1 |  SORT UNIQUE         |      |     6 |   156 |    15  (60)| 00:00:01 |
|   2 |   UNION-ALL          |      |       |       |            |          |
|*  3 |    HASH JOIN OUTER   |      |     3 |    78 |     7  (15)| 00:00:01 |
|   4 |     TABLE ACCESS FULL| A    |     3 |    39 |     3   (0)| 00:00:01 |
|   5 |     TABLE ACCESS FULL| B    |     3 |    39 |     3   (0)| 00:00:01 |
|*  6 |    HASH JOIN OUTER   |      |     3 |    78 |     7  (15)| 00:00:01 |
|   7 |     TABLE ACCESS FULL| B    |     3 |    39 |     3   (0)| 00:00:01 |
|   8 |     TABLE ACCESS FULL| A    |     3 |    39 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------

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

   3 - access("A"."ID"="B"."ID"(+))
   6 - access("A"."ID"(+)="B"."ID")

Note
-----
   - dynamic sampling used for this statement


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


显然,union连接的cpu代价要比full join连接来得多。此外,union还会暗含一个排序操作。当数据量海量时,估计会对性能带来一定的影响。而且,在oracle的私有语法里,是没有全外连接的,只能通过union连接来模拟full join。所以,建议需要使用外连接时,请使用full join,不要用union模拟。

分享到:
评论

相关推荐

    oracle性能优化技巧

    ORACLE的优化器共有3种 ... 在缺省情况下,ORACLE采用CHOOSE优化器, 为了避免那些不必要的全表扫描(full table scan) , 你必须尽量避免使用CHOOSE优化器,而直接采用基于规则或者基于成本的优化器

    Oracle SQL连接查询总结.docx

    缺省情况下是inner join,开发中使用的left join和right join属于outer join,另外outer join还包括full join.下面我通过图标让大家认识它们的区别。 现有两张表,Table A 是左边的表。Table B 是右边的表。其各有四条...

    sql学习笔记

    sql练习中易错笔记,order by ,group by,distinct,内连接,外连接等,一些mysql和oracle使用的区别:sql4种连接 两个表中有相同的列,根据共有的列值匹配行 left join左外连接,不管左表是否在右表中有匹配行,都...

    数据库oracle各种连接(+)解释.pdf

    连接无非是这几个  --内连接和where相同  inner join ... left join  --右向外连接,  right join  --完整外部连接,  full join  --交叉连接,也称笛卡儿积。 cross join .......

    视频教程读书笔记之oracle从入门到精通

    [LEFT | RIGHT | FULL OUTER JOIN 表名称2]; 1. 交叉连接:CROSS JOIN,主要功能是产生笛卡儿积,简单实现多表查询; SELECT * FROM emp CROSS JOIN dept; 2. 自然连接:NATURAL JOIN,自动使用关联字段消除...

    SQL语句生成及分析器

    内连接(inner join)和外连接(left join/right join/full join) 排序(Order By) 条件(Where) 分组(Group By) 分组条件(Having) 计算字段 SQL查询表 SQL查询子句 丰富的函数 表别名 字段别名 联合(Union...

    SQL语句生成及分析器(中文绿色)

    3.7.1 SQL 92 标准:Inner Join、Left Join、Right Join、Full Join, 3.7.2 特殊语法:*=、=*、*=*(MS_SQL,Sybase),(+)(Oracle) 3.8 联合 (Union [All],Minus,Intersect) 3.9 字段别名,数据表别名 ...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    ORACLE用户是学习ORACLE数据库中的基础知识,下面就介绍下类系统常用的默认ORACLE用户: 1. sys用户:超级用户,完全是个SYSDBA(管理数据库的人)。拥有dba,sysdba,sysoper等角色或权限。是oracle权限最高的用户,...

    Oracle 数据库连接查询SQL语句

    外连接: 全连接(full join)、左连接(left join)、右连接(right join)。 交叉联接(cross join)。 外连接与内连接不一样,外连接返回的查询结果中不仅包含符合条件的行,还包括左表(左外连接),右表(右外连接)...

    sql语句生成与分析器.rar

    3.7.1 SQL 92 标准:Inner Join、Left Join、Right Join、Full Join, 3.7.2 特殊语法:*=、=*、*=*(MS_SQL,Sybase),(+)(Oracle) 3.8 联合 (Union [All],Minus,Intersect) 3.9 字段别名,数据表别名 ...

    Oracle 外连接实现代码

    对于外连接,Oracle中可以使用“(+)”来表示,9i可以使用LEFT/RIGHT/FULL OUTER JOIN,下面将配合实例一一介绍。

    精通SQL数据库连接.doc

    一些数据库,如SQL Server, Oracle和DB2也支持JOIN HINT关键字的概念。这些关键字被插入到JOIN声明中来控制JOIN被处理的顺序。例如,一个MERGE JOIN会在处理其他连接之前将两个表格连接在一起。HASH JOIN会将一个...

    阿里巴巴大数据之路——数据技术篇.pdf

    实例参考如下: SQL的Join语法有很多, inner join(等值连接) 只返回两个表中联结字段相等的⾏, left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录, right join(右联接) 返回包括右表中的...

    关于关系表的连接操作在SQLSERVER与Oracle中测试大全

    这是我个人通过长时间的实践与收集最后总结出来的基本关系表的连接操作实际应用,以及在某些情况下可以用普通的sql语句代替某些连接操作(即实现同样的功能)其中文件夹中已经...ORACLE数据库直接用PL/SQL 导入就可。

    SQL培训第一期

    from student_A A full outer join student_B B on A.Uuid = B.Uuid; 1.6.4.3 结果 1.6.4.4 全外连接不支持(+)写法 1.6.5 (+) + 表示补充,即哪个表有加号,这个表就是匹配表。 1.7 运算符 1.7.1 比较 =、>,<,...

    SQL语法大全

    以上几个游标类型将直接影响到Recordset对象所有的属性和方法,以下列表说明他们之间的区别。 ------------------------------------------------------------- Recordset属性 adOpenForwardOnly adOpenKeyset ...

    经典全面的SQL语句大全

    select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where .....  12、说明:日程安排提前五分钟提醒 SQL: select * from 日程安排 where datediff('minute',f...

    Absolute Database for D7

    user and multi-user mode Full transactions support with ReadCommited isolation level SQL Support SELECT with DISTINCT, INNER LEFT, RIGTH, FULL and OUTER JOIN, GROUP BY and ORDER BY clauses CREATE ...

    经典SQL语句大全

    select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where ..... 12、说明:日程安排提前五分钟提醒 SQL: select * from 日程安排 where datediff('minute',f...

    数据库操作语句大全(sql)

    select * from a left inner join b on a.a=b.b right inner join c on a.a=c.c inner join d on a.a=d.d where ..... 12、说明:日程安排提前五分钟提醒 SQL: select * from 日程安排 where datediff('minute',f...

Global site tag (gtag.js) - Google Analytics