添加 2 表条件时,Oracle 左外连接停止返回结果
Posted
技术标签:
【中文标题】添加 2 表条件时,Oracle 左外连接停止返回结果【英文标题】:Oracle left outer join stops returning results when 2-table condition added 【发布时间】:2015-01-20 19:03:32 【问题描述】:我有一个包含一整串内连接和左连接的 oracle sql 查询。但是,当我添加最后一个左连接条件时,它会停止返回结果。这最终可能是一个简单的答案,例如“您不能对来自 2 个表的列进行外部联接”,但我找不到任何适用于 oracle 的规则,并且有很多示例显示相反的情况。 sql查询为:
FROM a, b,
c, d,
e, f,
g, h,
(SELECT id5 FROM
some_table WHERE
conditions) i,
(SELECT id7, type FROM
some_other_table WHERE
conditions) j
WHERE b.time in (range) AND
b.count <> 0 AND
b.id1 = e.id1 AND
e.type = g.type AND
g.type2 = f.type2 AND
b.id2 = a.id2(+) AND
b.time = a.time(+) AND
b.id3 = c.id3(+) AND
b.time = c.time(+) AND
c.id4 = d.id4(+) AND
c.time = d.time(+) AND
c.id5 = i.id5(+) AND
c.time = h.time(+) AND
c.id6 = h.id6(+) AND
h.id7 = j.id7(+); --AND
--e.type = j.type(+);
当我取消注释最终条件时,不会返回任何结果。由于这应该是外部连接,因此不应该发生这种情况。那么,这里的某些东西一定使它不像外部连接?
这里的某个地方有错字或错误吗?有没有我违反的预言规则?有什么可以通过切换到 ANSI 连接格式来解决的吗?
谢谢
【问题讨论】:
可能没有与新查询匹配的结果? 我确定没有。但它是一个外部连接。所以这不应该影响返回的行数。澄清问题。 是的,好点。那么,删除线后你会得到什么样的结果?任何看起来都会导致问题的东西,特别是从 e 或 j 表中收集的行? Ansi 语法是个不错的尝试。结果如何? 另一个猜测:您将 j 外部连接到两个不同的表 h 和 e。这似乎是使最后一行如此独特的一件事。如果你离开最后一行并取出它上面的那一行,看看是否会发生同样的事情。否则,这个查询对我来说太复杂了。 【参考方案1】:您在将查询转换为简单形式时遗漏了某些内容,或者我在操作中遗漏了某些内容,但看起来查询可能没有按照您认为的那样执行。以标准 ANSI 形式重写更能说明问题:
FROM a
right outer join b
on b.id2 = a.id2
AND b.time = a.time
right outer join c
on c.id3 = b.id3
AND c.time = b.time
left outer join d
on d.id4 = c.id4
AND d.time = c.time
join e
on e.id1 = b.id1
cross join f
join g
on g.type = e.type
AND g.type2 = f.type2
left outer join h
on h.time = c.time
AND h.id6 = c.id6
left outer join(
SELECT id5 FROM
some_table WHERE
conditions) i
on i.id5 = c.id5
left outer join(
SELECT id7, type FROM
some_other_table WHERE
conditions) j
on j.id7 = h.id7
and j.type = e.type --> the criteria in question
where b.time in (range)
AND b.count <> 0;
你觉得这合适吗?您没有提到 RIGHT OUTER 连接,但我希望您忘记了。您确实提到了 INNER 连接,但表 f 根本没有连接标准,所以我使用了 CROSS 连接,也希望这也是您的意图。
表 e 的连接条件是否应该是这样的?根据您设置的模式,我希望在这里看到“id5”而不是“id1”。当然,您已经更改了所有名称以提交简化示例,因此这可能没有意义。因此,我建议的第一件事是,您可以像我一样使用真实的表名和列名将原始代码重写为 ANSI 格式。你可能会看到一些东西。
您是正确的,添加标记的条件应该不会影响结果集中的行数。既然如此,那就有别的事情发生了。
要找出是什么,请注释掉整个最后一个连接。如果您发现有问题,请继续注释表格以找到问题所在。如果一切看起来都不错,只执行形成“表”j 的嵌套查询。我想不出它可能包含的任何内容会导致您解释的情况,但无论如何都要检查一下。
最后,如果所有其他方法都失败了,则只使用表 e 和 j 形成查询,然后只使用表 h 和 j(以及它们相应的连接条件)。看看会发生什么。
然后回到这里,向我们解释问题是如何一直存在于其他地方的。 :)
【讨论】:
我知道这是一个老问题,读完后我想知道为什么我没有评论你的答案,所以你可以编辑它,我可以选择它是正确的......我列出的所有标准是正确的,但我删除了任何不参与连接的内容。我的最终查询基本上看起来像你的,除了我在 f 之前加入了 g,避免了交叉连接(不记得为什么我没有按字母顺序命名表)。无论如何,原始查询包含足够的条件来避免完全外连接,但 Oracle 的语法规则没有考虑到这一点; ANSI 格式使其明确且有效。 哦,我还更改了顺序,以便所有外连接都是左外连接(以 b 开头),并且 f 确实具有与 g 的连接标准(您包括但可能由于 f 而错过在 g) 之前按字母顺序排列。以 b 开头是有充分理由的,但没有充分理由不以不同的顺序命名此问题中的表,因此我的简化示例以 :p 开头【参考方案2】:问题(如问题的 cmets 中所建议的)是 h.id7 = j.id7(+) AND e.type = j.type(+)
在功能上等同于 a.id1 = b.id1(+) and c.id2 = b.id2(+)
。 oracle join 语法不够精确,看不出来,由于其他连接条件,这不是全外连接,所以是不允许的。
这应该导致错误,但查询中的其他内容抑制了错误,我不清楚这是怎么发生的。无论如何,切换到 ANSI 格式使我能够更精确地指定连接条件,并且查询按预期工作。
【讨论】:
以上是关于添加 2 表条件时,Oracle 左外连接停止返回结果的主要内容,如果未能解决你的问题,请参考以下文章