关于左外连接和Where条件的SQL标准

Rya*_*yan 7 sql left-join

基于我放置过滤条件的位置,查询中的过滤条件会得到不同的结果.我的问题是:

  • 这些查询之间是否存在技术差异?
  • SQL标准中是否有任何内容可以解释查询中的不同记录集?

鉴于简化的方案:

--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,因为它是第一个答案,也是最清晰的答案之一.根据提供的答案,这是我的总结:

可能的结果:

  • 答:父母没有孩子
  • B:有孩子的父母
  • | - > B1:有孩子的孩子没有孩子匹配过滤器的父母
  • \ - > B2:父母与子女在一个或多个匹配过滤器

查询结果:

  • 查询1返回(A,B2)
  • 查询2返回(A,B1,B2)

由于左连接,查询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之后发生.

简而言之,第一个查询将排除存在子行但子描述不等于过滤条件的行,而第二个查询将始终返回父行的行.


mdm*_*dma 9

第一个查询将返回父项没有子项或某些子项与过滤条件匹配的情况.具体而言,父项具有一个子项但与过滤条件不匹配的情况将被省略.

第二个查询将为所有父项返回一行.如果过滤条件不匹配,则将为所有c列返回NULL.这就是为什么在查询2中获得更多行的原因 - 具有与过滤条件不匹配的子项的父项将使用NULL子值输出,其中在第一个查询中它们被过滤掉.