【问题标题】:Oracle outer join not giving expected results (behaving like inner join)Oracle 外连接未给出预期结果(行为类似于内连接)
【发布时间】:2012-09-09 20:57:04
【问题描述】:

这个查询:

select *
from table_a
, table_b
where table_a.id = table_b.id(+)
   and table_b.name = 'BENEFICIARY'

没有返回任何记录。 table_b 没有 name='BENEFICIARY' 的记录。但是外连接应该返回 table_a 中的所有记录。不? 以下查询按预期从 table_a 返回记录:

select *
from table_a
, (select *
   from table_b
   where table_b.name = 'BENEFICIARY') AS table_b1
where table_a.id = table_b1.id(+)

为什么第一个查询没有返回记录?

【问题讨论】:

  • 为什么是过时的语法?为什么不使用(符合ANSI!)“左/右连接”语法??????
  • 如果你使用 (+) 语法(我个人喜欢这种语法,因为 ANSI 语法很冗长),那么第 5 行应该是 table_b.name(+) = 'BENEFICIARY

标签: sql oracle11g inner-join outer-join


【解决方案1】:

旧式语法查询

select *
 from table_a
    , table_b
where table_a.id = table_b.id(+)
  and table_b.name = 'BENEFICIARY'

与 ANSI 查询相同

select *
 from table_a
      left outer join table_b on (table_a.id = table_b.id)
where table_b.name = 'BENEFICIARY'

在这两种情况下,谓词table_b.name = 'BENEFICIARY' 在连接之后应用,而不是作为连接的一部分,这违背了进行外连接的目的。为了确保谓词是连接操作的一部分,使用旧语法,您需要

select *
 from table_a
    , table_b
where table_a.id = table_b.id(+)
  and table_b.name(+) = 'BENEFICIARY'

虽然使用 ANSI 语法,但您会想要

select *
 from table_a
      left outer join table_b on (    table_a.id = table_b.id 
                                  and table_b.name = 'BENEFICIARY')

一般来说,如果您使用旧语法,任何您希望成为连接条件的一部分的谓词,而不是应用在连接之外的谓词,都需要将(+) 运算符应用于它。同样,当您使用 ANSI 语法时,您希望成为连接条件的一部分的谓词需要成为 ON 子句的一部分。

在这种情况下,ANSI 语法可能更容易解释,而且更便于移植,因此通常更受欢迎。

【讨论】:

    【解决方案2】:

    在第一个查询中,过滤器在连接之后应用于结果。

    试试

    select * 
    from table_a
         left join table_b 
         on table_a.id=table_b.id
         and table_b.name='BENEFICIARY'
    

    【讨论】:

    • 谢谢。但是为什么使用 ANSI 语法会改变过滤器在连接之后应用的事实呢?
    • 它没有。上面的查询没有where,所以过滤是在join上完成的
    猜你喜欢
    • 1970-01-01
    • 2015-11-01
    • 2017-09-07
    • 2013-08-06
    • 1970-01-01
    • 2013-09-28
    • 1970-01-01
    • 1970-01-01
    • 2018-04-16
    相关资源
    最近更新 更多