Oracle left outer join with is null in JOIN vs WHERE 条件(示例)
Posted
技术标签:
【中文标题】Oracle left outer join with is null in JOIN vs WHERE 条件(示例)【英文标题】:Oracle left outer join with is null in JOIN vs WHERE condition (example) 【发布时间】:2013-06-19 13:29:55 【问题描述】:我无法理解 Oracle 返回这个奇怪结果的原因。 我认为代码真的很清楚。
我期待 无条件 = (在 OUTER JOIN 条件下不为空) + (在 OUTER JOIN 条件下为空)
因为我将外部连接右表列中的 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
【问题讨论】:
【参考方案1】:EXISTS
/NOT EXISTS
等效查询是通过将NULL
条件放在WHERE
子句而不是OUTER JOIN
子句中获得的。顺便说一句,这是我们从您的结果中观察到的:
No condition 6403
is not null in where cond 6401
is null in where cond 2
主表中的 2 行在连接表中没有对应的 ID。
当您将条件放在OUTER JOIN
子句中时,您是在告诉Oracle 将OUTER JOIN
您的主表添加到连接表中的行子集。
由于c.flh_stato
永远不会为空,因此条件是多余的,我们得到的结果与无条件查询相同:
No condition 6403
is NOT null in OUTER JOIN cond 6403
使用join子句中的条件c.flh_stato IS NULL
,我们将主表连接到一个空的结果集,因此我们得到主表每一行的一行(我们用这个条件推导出主表有6247行):
is null in OUTER JOIN cond 6247
【讨论】:
真的很高兴知道。即使我认为 oracle 很奇怪......为什么允许在 JOIN 条件中预过滤表......这很奇怪......我想在 JOIN 条件中使用连接条件,也许是 EXIST / NOT EXIST 等价......不是预过滤器... @Gik25 我不确定这是特定于 Oracle 的。这似乎是 SQL 合成器的直接应用。请参阅mysql、MS SQL 中的这些示例。大多数情况下,NOT IN
或 NOT EXISTS
的反连接更容易理解,并且在 Oracle 中具有相同的优化器选项(但要注意空值)。以上是关于Oracle left outer join with is null in JOIN vs WHERE 条件(示例)的主要内容,如果未能解决你的问题,请参考以下文章
“,”“natural join”“natural left outer join”“natural right outer join”的用法总结
Left Outer Join 的条件谓词评估较晚,导致性能问题。甲骨文 8i
关于mysql中的left join和left outer join的区别