在 Oracle 查询中将连接从 Where 子句移动到 From 子句
Posted
技术标签:
【中文标题】在 Oracle 查询中将连接从 Where 子句移动到 From 子句【英文标题】:Move joins from Where clause to From clause in an Oracle query 【发布时间】:2020-11-05 03:14:20 【问题描述】:我有以下 Oracle 查询,我想将连接从 Where 子句移动到 From 子句
select
*
from
A, B, C
where
A.a (+)= B.a
AND A.b (+) = B.b
AND A.b = C.b;
所以我想出了以下查询
select
*
from
C,
B left join A on (B.a = A.a and B.b = A.b and C.b = A.b);
我想知道这两个查询在语义上是否相同,是否会输出相同的结果
*** 编辑:尝试 2
select
*
from
B left join A on (B.a = A.a and B.b = A.b)
inner join C on C.b = A.b;
【问题讨论】:
不要混合现代显式 JOIN 和旧的逗号分隔的。到处切换到显式 JOIN。 那个查询实际上是无效的,因为应该在找到逗号分隔的 C 之前评估 ON 子句。 @jarlh 我刚刚编辑了我的问题。也许第二次尝试等同于原始查询? Attempt 2 相当于你的第一个查询 我同意尝试 2 等同于您的第一个查询。这是从旧语法到新语法的正确转换。因此,这两个查询甚至在您实际上是在内部联接表 A 时,都使您看起来像是在外部联接表 A 的方面。 (对于相同的列顺序,它必须是select a.*, b.*, c.* ...
而不是 select *
,但这是一个小细节。)
【参考方案1】:
在旧的 Oracle 连接语法中,(+)
将应用于外连接表的所有列。因此,在您的原始查询中,表 A 与表 B 外连接,因为
FROM a, b
WHERE a.a (+) = b.a AND a.b (+) = b.b
是
FROM b
LEFT join a ON a.a = b.a AND a.b = b.b
但是AND a.b = c.b
在您的查询中呈现这仅仅是一个内部联接,因为它必须是AND a.b (+) = c.b
才能工作的外部联接(在这种情况下,您可能也需要a.b = c.b
,以免交叉连接两个表)。
所以您的查询归结为:
select *
from a
inner join b on b.a = a.a and b.b = a.b
inner join c on c.b = a.b;
【讨论】:
【参考方案2】:如果以下是您的工作查询,那么我必须说它没有达到预期的效果。
select
*
from
A, B, C
where
A.a (+)= B.a -- b left join a
AND A.b (+) = B.b -- b left join a
AND A.b = C.b; -- c inner join a
这不过是所有三个表的内连接,因为最后一个条件使它成为 a 和 c 之间的内连接。仅当 a 和 c(以及 b)中都有可用数据时,它才会返回数据。 (内连接)
要获得准确的结果,您只需要一个内连接。
SELECT * FROM
B INNER JOIN A ON A.A=B.A AND A.B = B.B
INNER JOIN C ON A.B = C.B
【讨论】:
【参考方案3】:您可能希望此查询为:
select *
from B left join
A
using (a, b) left join
C
using (b)
【讨论】:
以上是关于在 Oracle 查询中将连接从 Where 子句移动到 From 子句的主要内容,如果未能解决你的问题,请参考以下文章
如何强制 where 子句中的函数在 oracle 中执行一次?