Oracle左外部联接在联接vs WHERE条件中为null(示例)

Oracle左外部联接在联接vs WHERE条件中为null(示例),oracle,outer-join,Oracle,Outer Join,我无法理解Oracle返回这种奇怪结果的原因。 我认为代码真的很清楚 我预料 无条件=(在外部联接条件中不为null)+(在外部联接条件中为null) 因为我将外部联接右表列中的IS NULL/IS NOT NULL解释为EXISTS/NOT EXISTS条件 为什么我错了 DESCRIPTION COUNT(1) ---------------------------------- ---------- No condition

我无法理解Oracle返回这种奇怪结果的原因。 我认为代码真的很清楚

我预料 无条件=(在外部联接条件中不为null)+(在外部联接条件中为null)

因为我将外部联接右表列中的IS NULL/IS NOT NULL解释为EXISTS/NOT EXISTS条件

为什么我错了

DESCRIPTION                          COUNT(1)
---------------------------------- ----------
No condition                             6403
is NOT null in OUTER JOIN cond           6403
is not null in where cond                6401
is null in OUTER JOIN cond               6247
is null in where cond                       2
proof flh_id_messaggio is not null          0
proof flh_stato is not null                 0


  SELECT 'is null in OUTER JOIN cond ' description, count(1)
    FROM    netatemp.TMP_BACKLOG_NOBILLING2013 t
         LEFT OUTER JOIN
            eni_flussi_hub c ON
            c.flh_id_messaggio = t.flh_id_messaggio  
            AND c.flh_stato is null   
   WHERE 1 = 1 
       And t.flh_stato = 'PA'
         AND t.OWNER = 'ETL' 
UNION
  SELECT 'is NOT null in OUTER JOIN cond ' description, count(1)
    FROM    netatemp.TMP_BACKLOG_NOBILLING2013 t
         LEFT OUTER JOIN
            eni_flussi_hub c ON
            c.flh_id_messaggio = t.flh_id_messaggio  
            AND c.flh_stato is not null   
   WHERE 1 = 1 
       And t.flh_stato = 'PA'
         AND t.OWNER = 'ETL'
UNION
  SELECT 'is null in where cond ' description, count(1)
    FROM    netatemp.TMP_BACKLOG_NOBILLING2013 t
         LEFT OUTER JOIN
            eni_flussi_hub c ON
            c.flh_id_messaggio = t.flh_id_messaggio                
   WHERE 1 = 1 
       And t.flh_stato = 'PA'
         AND t.OWNER = 'ETL'
         AND c.flh_stato is null 
UNION
  SELECT 'is not null in where cond ' description, count(1)
    FROM    netatemp.TMP_BACKLOG_NOBILLING2013 t
         LEFT OUTER JOIN
            eni_flussi_hub c ON
            c.flh_id_messaggio = t.flh_id_messaggio                
   WHERE 1 = 1 
       And t.flh_stato = 'PA'
         AND t.OWNER = 'ETL'
         AND c.flh_stato is not null 
UNION
  SELECT 'No condition' description, count(1)
    FROM    netatemp.TMP_BACKLOG_NOBILLING2013 t
         LEFT OUTER JOIN
            eni_flussi_hub c ON
            c.flh_id_messaggio = t.flh_id_messaggio                
   WHERE 1 = 1 
       And t.flh_stato = 'PA'
         AND t.OWNER = 'ETL'
UNION select 'proof flh_stato is not null' description, count(1)
from eni_flussi_hub
where flh_stato is null         
UNION select 'proof flh_id_messaggio is not null' description, count(1)
from eni_flussi_hub
where flh_id_messaggio is null  

存在
/
不存在
等效查询是通过将
NULL
条件放置在
WHERE
子句中而不是
外部联接
子句中获得的。顺便说一下,这是我们从您的结果中观察到的:

No condition                             6403
is not null in where cond                6401
is null in where cond                       2
主表中的2行在联接表中没有相应的ID


当您在
外部联接
子句中放置条件时,您告诉Oracle将
外部联接
您的主表从联接表中转到一个行子集

由于
c.flh_stato
从不为空,因此该条件是冗余的,我们得到的结果与无条件查询相同:

No condition                             6403
is NOT null in OUTER JOIN cond           6403
如果join子句中的条件
c.flh_stato为NULL
,我们将主表连接到一个空结果集,因此主表的每行得到一行(我们推断主表有6247行具有此条件):


真的很高兴知道。即使我觉得甲骨文很奇怪。。。为什么允许在联接条件中预筛选表。。真奇怪。。我认为在连接条件中只使用连接条件,可能使用EXIST/NOT EXIST等效项。。不是预过滤器…@Gik25我不确定这是Oracle特有的。这似乎是SQLSynthax的一个直接应用程序。请参见中的这些行为类似的示例。通常情况下,使用
NOT IN
NOT EXISTS
的反连接更容易理解,并且在Oracle中具有相同的优化器选项(不过要注意空值)。
is null in OUTER JOIN cond               6247