外部加入在Oracle

时间:2017-08-03 13:19:21

标签: sql oracle join

  • 我有一个客户主表CUSTOMER_MASTER,它有一个主键CUSTOMER_ID
  • 客户CUSTOMER_DETAILS_1CUSTOMER_DETAILS_2还有两个子表,每个表都有自己的主键和外键CUSTOMER_ID
  • 并非主表CUSTOMER_MASTER中的所有记录都在上述两个子表中具有相应的记录。

我需要构建一个select语句,该语句根据键CUSTOMER_MASTER连接三个表CUSTOMER_DETAILS_1CUSTOMER_DETAILS_2CUSTOMER_ID。但问题是CUSTOMER_MASTER中的子记录中没有相应记录的记录即使使用外连接也不会出现在输出中。见下面的查询:

SELECT * 
FROM CUSTOMER_MASTER MAS, CUSTOMER_DETAILS_1 SUB1, CUSTOMER_DETAILS_2 SUB2
WHERE SUB1.CUSTOMER_ID = MAS.CUSTOMER_ID(+)
AND   SUB2.CUSTOMER_ID = MAS.CUSTOMER_ID(+)
-- Other conditions for CUSTOMER_DETAILS_1 and CUSTOMER_DETAILS_2 are there.

我的目标是选择以下所有客户:

Expected SQL Result

DB是Oracle 11g

2 个答案:

答案 0 :(得分:3)

不要使用过时的旧连接语法。它不那么强大(有些东西你不能用这种方式表达),它可能是模糊的(当一个条件是JOIN的一部分以及它是WHERE子句的一部分时,或条件属于哪个JOIN时,并不总是很清楚),它更难阅读,因为它混合了查询中的所有条件。至少从1999年开始,这或多或少已经过时了。

在这种情况下,可能是“1& 2”部分的“其他条件”是问题所在。由于JOIN和WHERE子句之间没有区别,因此它们将作为WHERE子句应用。但是,如果没有来自CUSTOMER_DETAILS_1CUSTOMER_DETAILS_2的记录,则条件与NULL进行比较,这有效地导致FALSE和整个CUSTOMER_MASTER }记录从结果集中排除。

使用旧语法并不总能很好地解决这个问题,但使用现代连接语法很容易。这可能会像你期望的那样工作:

SELECT * 
FROM CUSTOMER_MASTER MAS
LEFT JOIN CUSTOMER_DETAILS_1 SUB1 ON SUB.CUSTOMER_ID = MAS.CUSTOMER_ID
     -- AND other conditions for CUSTOMER_DETAILS_1
LEFT JOIN CUSTOMER_DETAILS_2 SUB2 ON SUB2.CUSTOMER_ID = MAS.CUSTOMER_ID 
     -- AND other conditions for CUSTOMER_DETAILS_2

这会强制将附加条件视为JOIN的一部分而不是WHERE,这样它们就不会导致CUSTOMER_MASTER记录被排除。

答案 1 :(得分:1)

尝试以下查询。您可以在sqlfiddler上查看架构和结果 http://sqlfiddle.com/#!4/40da3/3

SELECT 
    c.CustomerId,
    c.MasterDetails,
    d1.Details1,
    d2.Details2
FROM
                  Customers c
  LEFT OUTER JOIN CustomerDetails1 d1
          ON d1.CustomerId = c.CustomerId
  LEFT OUTER JOIN CustomerDetails2 d2
          ON d2.CustomerId = c.CustomerId
WHERE
    --Additonal where clause here
        1=1
    AND 2=2
    --etc
ORDER BY 
  c.CustomerId
相关问题