如何在 >2 个表上进行外部联接 (Oracle)
Posted
技术标签:
【中文标题】如何在 >2 个表上进行外部联接 (Oracle)【英文标题】:How to do Outer Join on >2 Tables (Oracle) 【发布时间】:2011-04-12 21:46:42 【问题描述】:我不确定如何描述我的表结构,所以希望这是有道理的...
我有 3 个层次关系表,因此 A 与 B 具有一对多关系,而 B 又与 C 具有一对多关系。诀窍是 B 和 C 中的外键允许为空(即没有定义父级)。我也有 D 和 E,与 A、B 或 C 无关(直接)。
最后,我有 F,它是一个与 C、D 和 E 具有多对一关系的连接表。它的所有字段(其他表的 FK)都不能为空。
我想编写一个 SQL 语句,将所有表连接到一个结果集中。我知道我必须使用外部联接,因为我希望返回所有 A,无论它在 B 中是否有子节点,并且与 B 和 C 类似。
问题一:我一直在看ANSI外连接语法(我之前只用过Oracle“(+)”),找不到外连接超过2个表的例子。有人可以提供/指出一个例子吗?
问题二: 是否可以根据连接表 F 包含表 D 和 E 中的记录?如果是这样,这是通过外部连接完成的吗?
谢谢!
编辑
当然,就在我发布这个之后,我找到了一个回答问题 1 的示例。但是,问题 2 仍然让我难过。
例子:
SELECT A.a,
B.b,
C.c
FROM A
FULL OUTER JOIN B ON B.a = A.a
FULL OUTER JOIN C ON C.b = B.b
【问题讨论】:
你可能不想要 FULL OUTER JOIN;它存在,但很少使用(或有用)。 您没有指定 F 中的哪些列与其他每个表连接 - 这意味着没有人可以给出明确的答案。 能否请您发布一些示例数据和您想要获取的记录集? A、B 和 C 的名称信息量不大。 @Jonathan,据我了解 ANSI 联接(我承认我只是在学习)我需要使用完全联接,因为我想要表 A 中的所有记录,即使其中没有子记录表 B 和表 B 中的所有记录,即使没有定义表 A 的外键。左连接或右连接只会给我一个关系方向的空值。表 F 只有 3 个字段,它们是表 C、D 和 E 的外键。Bill 在“绘制”模式的回答中做得很好。 【参考方案1】:所以我将您的架构可视化如下:
A --o< B --o< C --< F >-- D
>-- E
你当然可以做多个连接,你也可以用括号对连接表达式进行分组,就像你可以对算术表达式进行分组一样。
SELECT ...
FROM A LEFT OUTER JOIN (
B LEFT OUTER JOIN (
C LEFT OUTER JOIN (
F INNER JOIN D ON D.d = F.d
INNER JOIN E ON E.e = F.e
) ON C.c = F.c
) ON B.b = C.b
) ON A.a = B.a
这些括号不是子查询,它们只是对连接操作进行分组。
【讨论】:
这是“绘制”我的架构的好方法。谢谢!我需要花一些时间弄清楚您的 select 语句是否符合我的期望,但我确实认为我需要根据上面对 Jonathan 的评论使用 FULL 连接。【参考方案2】:为了清楚起见,大写字母指代表,小写字母指代主键/外键列。我可能应该把它写成类似于 Quassnoi,但会一直这样,因为它就是这样开始的。
此 SQL 返回我正在寻找的结果:
SELECT A.a,
B.b,
C.c,
D.d,
E.e
FROM A
FULL OUTER JOIN B ON B.a = A.a
FULL OUTER JOIN C ON C.b = B.b
FULL OUTER JOIN F ON F.c = C.c
FULL OUTER JOIN D ON D.d = F.d
FULL OUTER JOIN E ON E.e = F.e
我尝试像 Bill 一样设置我的 SQL,但使用 FULL 连接而不是 LEFT 连接,但它没有返回与我相同的结果。我不能说我完全理解他的 SQL,但是 INNER 连接过滤了一些结果。
【讨论】:
【参考方案3】: select a.*, b.*, c.*
from a
left outer join b on a.b_id = b.id
left outer join c on a.c_id = c.id
现在,在其中获取 D、E 和 F 变得更加棘手:
select c.*, d.*, e.*
from C
inner join f on c.id = f.c_id
inner join d on d.id = f.d_id
inner join e on d.id = f.e_id
然后我们把它们放在一起:
select a.*, b.*, cde.*
from a
left outer join b on a.b_id = b.id
left outer join
(select c.id as c_id, c.*, d.*, e.*
from C
inner join f on c.id = f.c_id
inner join d on d.id = f.d_id
inner join e on d.id = f.e_id) CDE
on a.c_id = cde.c_id
【讨论】:
谢谢!我们一定是同时发帖的。【参考方案4】:SELECT a.*, b.*, c.*, d.*, e.*
FROM a
LEFT JOIN
b
ON b.a = a.id
LEFT JOIN
с
ON c.b = b.id
LEFT JOIN
f
ON f.с = c.id
LEFT JOIN
d
ON d.id = f.d
LEFT JOIN
e
ON e.id = f.e
【讨论】:
以上是关于如何在 >2 个表上进行外部联接 (Oracle)的主要内容,如果未能解决你的问题,请参考以下文章