Oracle 中的连接表(多个外连接)

Posted

技术标签:

【中文标题】Oracle 中的连接表(多个外连接)【英文标题】:Joining tables in Oracle (multiple outer joins) 【发布时间】:2011-11-03 19:18:02 【问题描述】:

我正在尝试将 Informix 查询转换为 Oracle:

Informix 查询如下所示:

SELECT
    r.aa, n.bb, nd.cc,u.id, ud.dd, g.attr 
FROM
    tab1 u, tab2 ud, 
OUTER (tab3 a, tab4 n, tab5 nd, tab6 r, OUTER (tab7 g, tab8 atr))
WHERE
    r.xx = n.xx AND
    n.nas = a.nas AND
    a.user = u.user AND
    a.ac = g.ac AND
    n.nas1 = nd.nas1 AND
    u.user1 = ud.user1 AND
    atr.sso = g.sso AND
    UPPER(atr.name) = 'NAME' AND
    u.id = 102 

Oracle 查询如下所示:

SELECT
    r.aa, n.bb, nd.cc,u.id, ud.dd, g.attr
FROM
    tab1 u
INNER JOIN tab2 ud ON
    u.user1 = ud.user1 AND
    u.id = 102
LEFT OUTER JOIN tab3 a ON a.user = u.user 
LEFT OUTER JOIN tab4 n ON n.nas = a.nas
LEFT OUTER JOIN tab5 nd ON  n.nas1 = nd.nas1 
LEFT OUTER JOIN tab6 r ON r.xx = n.xx

我不确定如何加入其他两个表。

谁能帮帮我?

【问题讨论】:

Informax 语法是什么意思? 你试过SQLine吗? 【参考方案1】:

我相信查询应该是这样的:

SELECT r.aa, n.bb, nd.cc, u.id, ud.dd, g.attr
  FROM            tab1 AS u
       INNER JOIN tab2 AS v ON u.user1 = v.user1 AND u.id = 102
  LEFT OUTER JOIN tab3 AS a ON a.user  = u.user 
  LEFT OUTER JOIN tab4 AS n ON n.nas   = a.nas
  LEFT OUTER JOIN tab5 AS d ON n.nas1  = d.nas1 
  LEFT OUTER JOIN tab6 AS r ON r.xx    = n.xx
  LEFT OUTER JOIN (SELECT g.attr, g.ac
                     FROM tab7 AS x
                     JOIN tab8 AS atr ON x.sso = atr.sso
                    WHERE UPPER(atr.name) = 'NAME'
                  )    AS g ON a.ac    = g.ac

我将别名“nd”更改为“d”,将“ud”更改为“v”,以便所有别名都是单字母。 Informix 表示法中的嵌套OUTER(tab7 g, tab8 atr) 本身就是一个内连接(就像我的版本中的子选择一样),但该结果集是与a.ac 外连接的。重写是这么说的。

我在子查询中使用了 WHERE 子句;如果您愿意,可以将 WHERE 条件留在 ON 子句中。优化器可能会正确且等效地处理。类似地,内部连接中的AND u.id = 102 可以放入 WHERE 子句中。同样,优化器可能会降低过滤条件以获得更好的性能。

请注意,子查询中的 UPPER 函数可能需要进行表扫描 - 除非您在 UPPER(atr.name) 上有功能索引。


重温一下,查询的开头部分的音译不准确。

原始查询包含 FROM 子句:

FROM tab1 u, tab2 ud, OUTER(tab3 a, tab4 n, tab5 nd, tab6 r, OUTER(tab7 g, tab8 atr))

tab3tab4tab5tab6 相互内连接,结果外连接到tab1tab2。类似地,tab8 内连接到 tab7,但其结果是外连接到表 3-6 的内连接。我给出的原始答案(基于问题中的大纲答案)将使用旧的 Informix 表示法表示:

FROM tab1 u, tab2 ud,
     OUTER(tab3 a, OUTER(tab4 n, OUTER(tab5 nd, OUTER(tab6 r, OUTER(tab7 g, tab8 atr)))))

因此,将原始查询转录为:

SELECT r.aa, n.bb, nd.cc, u.id, ud.dd, g.attr
  FROM tab1 AS u
  JOIN tab2 AS v ON u.user1 = v.user1 AND u.id = 102
  LEFT OUTER JOIN
       (SELECT *
          FROM tab3 AS a ON a.user  = u.user 
          JOIN tab4 AS n ON n.nas   = a.nas
          JOIN tab5 AS d ON n.nas1  = d.nas1 
          JOIN tab6 AS r ON r.xx    = n.xx
          LEFT OUTER JOIN
               (SELECT g.attr, g.ac
                 FROM tab7 AS x
                 JOIN tab8 AS atr ON x.sso = atr.sso
                WHERE UPPER(atr.name) = 'NAME'
               )    AS g ON a.ac    = g.ac
       ) AS loj

剩余的问题是确保为复杂的loj 子查询中的列使用正确的别名。请注意,在没有 LEFT、RIGHT 或 FULL 的情况下,JOIN 被假定为 INNER 连接;此外,如果您指定 LEFT、RIGHT 或 FULL,则 OUTER 是可选的。

另一个需要注意的细节:旧式 Informix OUTER 联接在过滤条件下的行为与标准 SQL OUTER 联接的行为不同。这很少会产生影响,但有时可能很重要。总的来说,标准 SQL OUTER 联接的行为通常是您想要的,但是如果您运行回归测试并发现答案有所不同,解释可能是旧式 Informix OUTER 联接做的事情不同来自新型标准 SQL OUTER 连接。

【讨论】:

【参考方案2】:

我会尝试添加这些:

LEFT OUTER JOIN tab7 g ON a.ac = g.ac
LEFT OUTER JOIN tab8 atr ON g.sso = atr.sso AND UPPER(atr.name) = 'NAME'

【讨论】:

表 tab7 和 tab8 是内连接的;复合结果外连接到其他表。 AND upper(atr.name) 将删除连接的左外部性质。

以上是关于Oracle 中的连接表(多个外连接)的主要内容,如果未能解决你的问题,请参考以下文章

oracle连接总结(内连接外连接自然连接,交叉连接,自连接)

ORACLE:多表连接查询

Oracle 多表查询

SQL内连接与外连接的区别

sql server 2005 中的内连接和外连接 怎么理解?

SQL中的左连接与右连接,内连接有啥区别