JOIN 获取第一个表中的所有行以及第二个表中的 NULL

Mar*_*urn 3 join sql-server

我有两张桌子(tblRepstblDailyWorkingTime)。该tblReps表,即第一个,返回 37 行,但是当我将它与第二个表连接时,我得到 36 行,因为第二个表只有 36 行与第一个表匹配。

如何使用不匹配的行的 NULL 结果返回 37 行?

这是我到目前为止的查询:

SELECT 
    tblReps.[sName] AS 'RepName',
    tblReps.sNote AS 'Type',
    RIGHT(CAST(tblDaily.sDateAndTimeStart  AS smalldatetime), 8) AS 'DayStarted'

FROM 
    [tblRepresentatives] AS tblReps

FULL OUTER JOIN 
    tblDailyWorkingTime AS tblDaily ON tblDaily.sRepresentativeCode = tblReps.sCode 

WHERE 
    tblDaily.sDate = CAST(GETDATE() AS DATE)
    AND tblReps.[sActive] = 'True'
Run Code Online (Sandbox Code Playgroud)

And*_*y M 8

首先,在这种情况下使用的正确连接类型是左连接:

...
FROM 
    [tblRepresentatives] AS tblReps

LEFT OUTER JOIN 
    tblDailyWorkingTime AS tblDaily ON tblDaily.sRepresentativeCode = tblReps.sCode 
...
Run Code Online (Sandbox Code Playgroud)

在您的特定情况下,您仍然可以使用,FULL因为WHERE无论如何这个条件都会将其变成左连接:

tblReps.[sActive] = 'True'
Run Code Online (Sandbox Code Playgroud)

但最好能准确表达意图。

将您的完全连接变成左连接的相同效果实际上是造成您预期的第 37 行丢失的原因。更具体地说,这个其他WHERE条件:

tblDaily.sDate = CAST(GETDATE() AS DATE)
Run Code Online (Sandbox Code Playgroud)

将您的 join 进一步转换为内部 join。这就是输出中缺少第 37 行的原因。

发生这种情况的原因是这样的。该FROM子句tblDaily.sDate为不匹配的行返回空值。由于该WHERE条款逻辑执行FROM,上述断言排除不匹配的行,因为NULL = CAST(GETDATE() AS DATE)不会评估为True。

您需要做的是将sDate条件移至ON子条款:

...
FROM 
    [tblRepresentatives] AS tblReps

LEFT OUTER JOIN 
    tblDailyWorkingTime AS tblDaily ON tblDaily.sRepresentativeCode = tblReps.sCode
                                   AND tblDaily.sDate = CAST(GETDATE() AS DATE)

WHERE 
    tblReps.[sActive] = 'True'
Run Code Online (Sandbox Code Playgroud)

这样,tblDaily.sDate = CAST(GETDATE() AS DATE) 联接发生之前,联接的右侧就被过滤掉了。因此,查询将返回预期的 37 行,来自tblReps补充的匹配数据tblDaily或空值。