我遇到了一个问题,我无法弄清楚如何正确配置连接。我正在使用报告软件,该软件利用WHERE子句中的(+)指标为我们的Oracle数据库。我有两张桌子:
检查和交易。支票可以有多个交易,但交易不一定有相应的支票。
两个表都有指示器,用于标识名为CURRENT的当前记录,即“Y”或“N”。
加入选项1:
json_encode()
加入选项2:
Select *
FROM TXN,CHK
WHERE
TXN.CHK_ID = CHK.CHK_ID(+)
and TXN.CURRENT = 'Y'
and CHK.CURRENT = 'Y'
这些连接产生不同的结果,我似乎无法弄清楚当应用于CHK.CURRENT字段时额外的外连接指示符有什么影响。带有额外指标的查询会产生更大的结果集。有人可以帮忙解释一下这里发生了什么吗?
答案 0 :(得分:6)
我将通过使用等效的“ANSI JOIN”语法来解释这一点:
SELECT *
FROM TXN
LEFT JOIN CHK
ON TXN.CHK_ID = CHK.CHK_ID
WHERE TXN.CURRENT = 'Y'
AND CHK.CURRENT = 'Y'
SELECT *
FROM TXN
LEFT JOIN CHK
ON TXN.CHK_ID = CHK.CHK_ID
AND CHK.CURRENT = 'Y'
WHERE TXN.CURRENT = 'Y'
正如您所看到的,在选项1中,在指定LEFT JOIN
表表达式之后,即LEFT JOIN
的结果,应用。
在选项2中,您的一个常量谓词是LEFT JOIN
表达式的一部分。
LEFT JOIN
如何运作? LEFT JOIN
的想法是它将返回JOIN
表达式的 LEFT 侧的所有行,无论另一侧是否有匹配的行,给定连接谓词。因此,在选项2中,无论您在CHK
中找到CURRENT = 'Y'
行还是TXN
中的行,都会返回TXN
中的行。这就是您在选项2中获得更多行的原因。
此外,此示例应解释为什么您应该更喜欢“ANSI JOIN”语法。从维护/可读性的角度来看,您的查询正在做的事情要清楚得多。
答案 1 :(得分:2)
。(+)
运算符告诉Oracle谓词是外连接的一部分,而不是可以在连接后应用的过滤谓词。使用SQL 99外连接语法,第一个查询等同于
SELECT *
FROM txn
left outer join chk
on( txn.chk_id = chk.chk_id )
WHERE txn.current = 'Y'
AND chk.current = 'Y'
而第二个相当于
SELECT *
FROM txn
left outer join chk
on( txn.chk_id = chk.chk_id AND
chk.current = 'Y')
WHERE txn.current = 'Y'
逻辑上,在第一种情况下,您执行外部联接,但随后将chk.current
NULL
chk.current = 'Y'
的所有行过滤掉。在第二种情况下,chk
条件不会过滤掉任何行,它只控制是否在class table:
def __init__(self):
self.h = 0
self.g = 0
中找到匹配的行,或者是否执行了左外连接。
答案 2 :(得分:0)
加入选项1将仅考虑CHK.CURRENT =' Y'的那些行。因此,如果事务没有检查,CHK.CURRENT将为NULL,并且该行不在结果集中。
加入选项2将考虑CHK.CURRENT(如果有检查)是' Y'的那些行。如果事务没有检查,则不会应用此测试,并且该行将位于结果集中。
您可以看到与此比较的区别:
Select *
FROM TXN,CHK
WHERE
TXN.CHK_ID = CHK.CHK_ID(+)
and TXN.CURRENT = 'Y'
and CHK.CURRENT(+) = 'Y'
MINUS
Select *
FROM TXN,CHK
WHERE
TXN.CHK_ID = CHK.CHK_ID(+)
and TXN.CURRENT = 'Y'
and CHK.CURRENT = 'Y'
答案 3 :(得分:0)
加入选项1相当于:
SELECT *
FROM TXN
LEFT OUTER JOIN CHK
ON ( TXN.CHK_ID = CHK.CHK_ID )
WHERE TXN.CURRENT = 'Y'
AND CHK.CURRENT = 'Y'
但是,由于结果集中的任何行都将具有CHK.CURRENT = 'Y'
(非空值),因此这些行必须在CHK_ID
上匹配,并且查询实际上相当于:< / p>
SELECT *
FROM TXN
INNER JOIN CHK
ON ( TXN.CHK_ID = CHK.CHK_ID )
WHERE TXN.CURRENT = 'Y'
AND CHK.CURRENT = 'Y'
加入选项2相当于:
SELECT *
FROM TXN
LEFT OUTER JOIN CHK
ON ( TXN.CHK_ID = CHK.CHK_ID
AND CHK.CURRENT = 'Y' )
WHERE TXN.CURRENT = 'Y'
您可以使用以下方式使加入选项1等同于选项2
SELECT *
FROM TXN
LEFT OUTER JOIN CHK
ON ( TXN.CHK_ID = CHK.CHK_ID )
WHERE TXN.CURRENT = 'Y'
AND ( CHK.CURRENT = 'Y' OR CHK.CHK_ID IS NULL )