LEFT JOIN根据WHERE条件的位置给出不同的数据集

时间:2014-08-25 12:09:34

标签: sql sql-server sql-server-2008 tsql sql-server-2012

请参阅下面的3个计数,只是为了简要介绍一下表格数据。 skCitizen

中存在[dbo].[LUEducation]中的所有[dbo].[LUCitizen]
SELECT  COUNT(*) FROM   [dbo].[LUCitizen] --115000 ROWS
SELECT  COUNT(*) FROM   [dbo].[LUEducation]  --201846 ROWS

SELECT  COUNT(*) --212695 ROWS
FROM    [dbo].[LUCitizen] C
LEFT JOIN   [dbo].[LUEducation] E
ON      C.skCitizen = E.skCitizen

SELECT  COUNT(*) FROM   [dbo].[LUEducation] WHERE skSchool = 24417 --4 ROWS

请参阅以下2个查询,

SELECT  C.skCitizen,E.skCitizen
FROM    [dbo].[LUCitizen] C
LEFT JOIN   [dbo].[LUEducation] E
ON      C.skCitizen = E.skCitizen
WHERE   E.skSchool = 24417
--4 ROWS

SELECT  C.skCitizen,E.skCitizen
FROM    [dbo].[LUCitizen] C
LEFT JOIN   (SELECT * FROM [dbo].[LUEducation] WHERE skSchool = 24417) E
ON      C.skCitizen = E.skCitizen
--115000 ROWS

在最后两个查询中,对我来说令人困惑的查询是第一个。我预计115000 rows,但只显示4 rows。 根据我的理解,将显示[dbo].[LUCitizen]中的完整行,然后[dbo].[LUEducation]中的4行将LEFT加入。

为什么2个查询不同?

请原谅我,如果这是一个重复的问题。

2 个答案:

答案 0 :(得分:8)

执行此操作时:

SELECT  C.skCitizen,E.skCitizen
FROM    [dbo].[LUCitizen] C
LEFT JOIN   [dbo].[LUEducation] E
ON      C.skCitizen = E.skCitizen
WHERE   E.skSchool = 24417;

您正在将left join变为inner join,因为对于不匹配的行,E.skSchoolNULL。将条件放在left join中的 second 表上的正确方法是使用on子句:

SELECT  C.skCitizen,E.skCitizen
FROM    [dbo].[LUCitizen] C
LEFT JOIN   [dbo].[LUEducation] E
ON      C.skCitizen = E.skCitizen AND E.skSchool = 24417;

答案 1 :(得分:3)

如果left join未能在E中找到匹配项,则E中的列会收到null值。然后是where子句:

E.skSchool = 24417

变为:

null = 24417

哪个不是真的。所以它会过滤掉所有行。