How can a LEFT OUTER JOIN return more records than exist in the left table?
我有一个非常基本的LEFT OUTER JOIN来返回左表中的所有结果以及来自更大表的一些附加信息。左表包含4935条记录,但当我将其连接到另一个表时,记录计数明显更大。
据我所知,LEFT OUTER JOIN将返回左表中的所有记录以及右表中的匹配记录和任何无法匹配的行的空值,这是绝对的福音,因此我的理解是它应该不可能返回比左表中存在的行更多的行,但它发生的一切都是一样的!
SQL查询如下:
1 2 3 | SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID FROM SUSP.Susp_Visits LEFT OUTER JOIN DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum |
也许我在语法上犯了一个错误,或者我对LEFT OUTER JOIN的理解是不完整的,希望有人可以解释这是如何发生的?
后记
感谢你们给出了很好的答案,我对LEFT OUTER JOINS的理解现在好多了,但是有人可以提出一种方法可以修改这个查询,这样我只能获得左表中存在的返回记录数量吗?
此查询纯粹是为了生成报告,而重复的匹配只是简单地混淆了问题。
/后记
LEFT OUTER JOIN将尽可能返回与RIGHT表连接的LEFT表中的所有记录。
如果有匹配,它仍将返回匹配的所有行,因此,LEFT中与RIGHT中的两行匹配的一行将返回为两个ROWS,就像INNER JOIN一样。
编辑:
为了回应您的编辑,我只是?徊讲榭戳四牟檠雌鹄茨皇谴覮EFT表返回数据。因此,如果您只需要来自LEFT表的数据,并且您只希望为LEFT表中的每一行返回一行,那么您根本不需要执行JOIN,只需直接从LEFT表执行SELECT。
1 2 3 4 5 6 7 8 | Table1 Table2 _______ _________ 1 2 2 2 3 5 4 6 SELECT Table1.Id, Table2.Id FROM Table1 LEFT OUTER JOIN Table2 ON Table1.Id=Table2.Id |
结果:
1 2 3 4 5 | 1,NULL 2,2 2,2 3,NULL 4,NULL |
这不是不可能的。左表中的记录数是它将返回的最小记录数。如果右表有两条记录与左表中的一条记录匹配,则它将返回两条记录。
在回复您的后记时,这取决于您的需求。
您可以为左表中的每一行获取(可能)多行,因为连接条件有多个匹配项。如果您希望总结果的行数与查询左侧的行数相同,则需要确保连接条件与1对1匹配。
或者,根据您的实际需要,您可以使用聚合函数(例如,如果您只需要来自右侧部分的字符串,则可以生成一个列,该列是右侧结果的逗号分隔字符串,用于该左侧行。
如果您只查看外部联接中的1或2列,则可以考虑使用标量子查询,因为您将获得1个结果。
左表中的每条记录将返回与右表中匹配记录一样多的次数 - 至少为1,但可能很容易超过1。
就像INNER JOIN(普通连接)一样,LEFT OUTER JOIN将为左表中的每一行返回尽可能多的结果,因为它在右表中找到了许多匹配。因此,您可以获得大量结果 - 最多N x M,其中N是左表中的行数,M是右表中的行数。
在LEFT OUTER JOIN中,始终保证最小结果数至少为N.
如果在包含左外连接的查询的"右侧"表上有where子句,请注意...
如果右侧没有满足where子句的记录,那么"左侧"表的相应记录将不会出现在查询结果中....
这可能是左右桌子之间的一对多关系吗?
如果你需要从右侧任何一行
1 2 3 4 5 6 7 | SELECT SuspReason, SiteID FROM( SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID, ROW_NUMBER() OVER(PARTITION BY SUSP.Susp_Visits.SiteID) AS rn FROM SUSP.Susp_Visits LEFT OUTER JOIN DATA.Dim_Member ON SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum ) AS t WHERE rn=1 |
要不就
1 2 3 4 | SELECT SUSP.Susp_Visits.SuspReason, SUSP.Susp_Visits.SiteID FROM SUSP.Susp_Visits WHERE EXISTS( SELECT DATA.Dim_Member WHERE SUSP.Susp_Visits.MemID = DATA.Dim_Member.MembershipNum ) |
如果Dim_Member中的多个(x)行与Susp_Visits中的单个行相关联,则结果集中将有x行。
似乎每个SUSP.Susp_Visits行的DATA.Dim_Member表中有多行。