基于我放置过滤条件的位置,查询中的过滤条件会得到不同的结果.我的问题是:
鉴于简化的方案:
--Table: Parent Columns: ID, Name, Description
--Table: Child Columns: ID, ParentID, Name, Description
--Query 1
SELECT p.ID, p.Name, p.Description, c.ID, c.Name, c.Description
FROM Parent p
LEFT OUTER JOIN Child c ON (p.ID = c.ParentID)
WHERE c.ID IS NULL OR c.Description = 'FilterCondition'
--Query 2
SELECT p.ID, p.Name, p.Description, c.ID, c.Name, c.Description
FROM Parent p
LEFT OUTER JOIN Child c
ON (p.ID = c.ParentID AND c.Description = 'FilterCondition')
Run Code Online (Sandbox Code Playgroud)
我假设查询将返回相同的结果集,当他们没有时,我感到很惊讶.我正在使用MS SQL2005并且在实际查询中,查询1返回~700行,查询2返回~1100行,我无法检测返回行和排除哪些行的模式.查询1中仍有许多行,子行包含数据和NULL数据.我更喜欢查询2的样式(我认为它更优),但我认为查询会返回相同的结果.
编辑/概述:
这里提供了一些很棒的答案.我很难选择给谁答案.我决定选择mdma,因为它是第一个答案,也是最清晰的答案之一.根据提供的答案,这是我的总结:
可能的结果:
查询结果:
由于左连接,查询2始终返回父级.在查询1中,WHERE子句在左连接之后执行,因此排除子节点中没有子节点匹配过滤器的父节点(情况B1).
注意:在B1的情况下仅返回父信息,在B2的情况下,仅返回与过滤器匹配的父/子信息.
HLGEM提供了一个很好的链接:
http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN
Tho*_*mas 10
是的,存在巨大差异.将过滤器放在LEFT JOIN上的ON子句中时,将在结果连接到外部表之前应用过滤器.在WHERE子句中应用过滤器时,它会在应用LEFT JOIN之后发生.
简而言之,第一个查询将排除存在子行但子描述不等于过滤条件的行,而第二个查询将始终返回父行的行.
第一个查询将返回父项没有子项或某些子项与过滤条件匹配的情况.具体而言,父项具有一个子项但与过滤条件不匹配的情况将被省略.
第二个查询将为所有父项返回一行.如果过滤条件不匹配,则将为所有c列返回NULL.这就是为什么在查询2中获得更多行的原因 - 具有与过滤条件不匹配的子项的父项将使用NULL子值输出,其中在第一个查询中它们被过滤掉.