你什么时候INNER JOIN LEFT JOINed表/

时间:2013-11-27 10:41:32

标签: sql sql-server

我今天遇到了以下代码。

SELECT StaffGroup.*
FROM StaffGroup
LEFT OUTER JOIN StaffByGroup 
  ON StaffByGroup.StaffGroupId = StaffGroup.StaffGroupId
INNER JOIN StaffMember 
   ON StaffMember.StaffMemberId = StaffByGroup.StaffMemberId
WHERE StaffByGroup.StaffGroupId IS NULL

主表StaffGroup正在与StaffByGroup表进行LEFT JOIN,然后StaffByGroup表正在与StaffMember表进行内联。

我认为INNER JOIN正在尝试过滤掉StaffGroupStaffByGroup中存在但StaffMember中不存在的记录。

但这不是它的工作方式。查询不会返回任何记录。

我在理解查询逻辑时遗漏了什么?你有没有使用INNER JOIN和一个在查询的前面部分与LEFT JOIN一起使用的表?

3 个答案:

答案 0 :(得分:2)

其实你错过了一个概念: 主表StaffGroup正在LEFT JoinedStaffByGroup表,然后创建virtual tableVT1,其中包含来自StaffGroup的所有记录以及来自StaffByGroup的匹配记录ON谓词中的匹配/过滤条件。那么不是StaffByGroup表,而是VT1根据INNER Joined中的匹配/过滤条件,StaffMemberON谓语。 所以基本上内部联接试图从StaffGroup过滤掉那些没有StaffMemberId的StaffByGroup记录。 添加where条件会添加最终过滤器,例如从上面所有连接创建的最终虚拟表中删除所有没有StaffGroupId的记录,而这些记录又可能会删除VT1中收集的所有行将为StaffGroupId提供一些价值。

要获取StaffGroup中没有StaffGroupId的所有记录以及StaffMember中所有此类记录的详细信息,您可以在ON谓词中添加条件:

SELECT StaffGroup.*
FROM StaffGroup
LEFT OUTER JOIN StaffByGroup 
  ON StaffByGroup.StaffGroupId = StaffGroup.StaffGroupId and StaffByGroup.StaffGroupId IS NULL
INNER JOIN StaffMember 
   ON StaffMember.StaffMemberId = StaffByGroup.StaffMemberId

答案 1 :(得分:1)

由于您的where clause

,您获得了0条记录
where StaffByGroup.StaffGroupId is null

left join链接来自tbl A的所有记录,这些记录包含在tbl B中,因为您已指定StaffGROUPID作为密钥,然后在密钥中查找Nulls个值, 100%明确表示你最终没有结果

答案 2 :(得分:1)

这个查询看起来存在根本缺陷 - 我想最初的目的是

SELECT StaffGroup.*
FROM StaffGroup
LEFT OUTER JOIN 
  (SELECT * FROM StaffByGroup 
   INNER JOIN StaffMember 
   ON StaffMember.StaffMemberId = StaffByGroup.StaffMemberId) StaffByGroup
ON StaffByGroup.StaffGroupId = StaffGroup.StaffGroupId
WHERE StaffByGroup.StaffGroupId IS NULL

返回StaffGroup中没有分配给他们的现有人员的所有组(带有StaffMember的INNER JOIN过滤掉StaffByGroup中没有StaffMember中匹配行的那些行 - 可能是因为他们之间不存在外键)