SELECT a.org,
a.id,
a.Name,
b.ordNum
FROM customers A,
orders B
WHERE a.org = 'JJJ'
AND a.org = b.org (+)
AND b.addr_type (+) = 'ST' -- <<<<<<<<<<<<<<<<< why do i need to add (+) here
AND a.cust_id = b.cust_id (+)
ORDER BY 2
我有一张表,其中包含客户列表(A)和一张名为订单(B)的表,其中包含客户可能已下达的订单。 我上面的查询应该给我所有客户的名字和订单号,如果有订单链接到该客户。
我的问题是..为什么我需要在b.addr_type之后添加(+)以获得所有客户,即使他们没有下订单。
答案 0 :(得分:4)
这是旧式JOIN
语法,其中(+)
表示OUTER JOIN
。这意味着无论是否在右表上匹配,左表中的每一行都将被返回。要仅获得订单的客户,请使用INNER JOIN
。此外,您应该使用显式JOIN
而不是旧式语法:
SELECT
c.ORG, c.ID, c.NAME, o.ordNum
FROM customers c -- Use meaningful aliases to improve readability
LEFT JOIN orders o
ON c.org = o.org
AND c.cust_id = o.cust_id
AND o.addr_type = 'ST'
WHERE
c.org = 'JJJ'
ORDER BY c.ID
答案 1 :(得分:3)
(+)是旧式语法中的“外连接”。这意味着如果没有匹配,则返回连接左侧的每一行,并在右侧表的列中返回“null”。
如果右侧没有匹配项,INNER连接(旧式SQL中的常规等号)将不会返回记录。
现代语法
SELECT A.ORG, A.ID, A.NAME, b.ordNum FROM
customers A
LEFT OUTER JOIN customers b on a.id = b.id
AND a.cust_id = b.cust_id
AND b.addr_type = 'ST'
WHERE a.org = 'JJJ'
ORDER BY 2
“OUTER”部分是可选的,如果您使用“LEFT”这个词,则确实是隐含的。对于外连接,您的其他选项是正确的和完全的。
为什么要使用这种新语法?因为它符合ANSI SQL,所以(+)不推荐使用,不会移植到某些现代RDBMS实现。另外,根据这篇文章的评论,它就像罪恶一样难以维持。
答案 2 :(得分:2)
为了避免这样的问题,
切换到LEFT JOIN
语法更易读
SELECT a.org,
a.id,
a.Name,
b.ordNum
FROM customers a LEFT JOIN
orders b ON (a.org = b.org)
AND (b.addr_type = 'ST')
AND (a.cust_id = b.cust_id)
WHERE a.org = 'JJJ'
ORDER BY a.id -- better put it direct, not field's index
答案 3 :(得分:2)
(+)语法告诉Oracle执行左连接而不是内连接。
结果是一个记录列表,其中包含customers
的所有增值列和orders
表中的一些空列。
如果orders
表中的列为NULL
,则这些记录的where条件b.addr_type = 'ST'
始终为FALSE
,因此您无法获得所需的结果。< / p>
相反,如果您编写b.addr_type(+) = 'ST'
,您将获得与条件匹配的所有列以及具有NULL
值的列,因为左连接,这就是您想要获得的。