【问题标题】:How to do Outer Join on >2 Tables (Oracle)如何在 >2 个表上进行外部联接 (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 在“绘制”模式的回答中做得很好。

标签: oracle outer-join multiple-tables


【解决方案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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-07
      • 1970-01-01
      • 1970-01-01
      • 2011-01-06
      • 1970-01-01
      相关资源
      最近更新 更多