SQL左连接不包括左表中的所有记录

Posted

技术标签:

【中文标题】SQL左连接不包括左表中的所有记录【英文标题】:SQL left join is not including all records from left table 【发布时间】:2021-04-27 11:32:37 【问题描述】:

我需要获取每个员工在不同任务上的每月总工作时数。为此,我正在编写一个存储过程。但是左连接没有填充员工表中的所有记录。 我知道 where 条件过滤掉了 null 值,但我真的不知道如何克服这个问题。

ALTER PROCEDURE [dbo].[GetEmployeeWorkHours]
@PageSize smallint = 10,
@CurrentPage smallint = 1,
@EmployeeId varchar(1000) = null,
@StartDate datetime = null,
@EndDate datetime = null
AS

 BEGIN

if(@StartDate is null)
select @StartDate = DATEADD(month, DATEDIFF(month, 0, getDate()), 0)

if(@EndDate is null)
select @EndDate = getDate()

select   e.Id,
e.FirstName + ' ' + e.LastName as [Name],
sum([Minutes]/60.0) as [WorkedHours]
from Employees e
left join TaskResources tr on (e.Id = tr.EmployeeId)
inner join ResourceTaskSchedules rts on (tr.Id = rts.TaskResourceId)
inner join TaskTimeSheets tts on (rts.Id = tts.ResourceTaskScheduleId)
where
((@EmployeeId is null) or (e.Id in (select splitdata from dbo.SplitEmployeeIds(@EmployeeId, ',')))) and
cast(tts.CheckIn as date) >= @StartDate
and cast(tts.CheckIn as date) <= @EndDate
group by
e.Id
ORDER BY
 e.Id
OFFSET (@CurrentPage-1)*@PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY; 

结束

【问题讨论】:

【参考方案1】:

from 子句中使用left join 后,通常会继续使用left join。如果第二个表用于任何条件,这一点至关重要。

然后,任何左连接表上的任何过滤条件都需要在on 子句中,而不是where 子句中。所以:

from Employees e left join
     TaskResources tr
     on e.Id = tr.EmployeeId left join
     ResourceTaskSchedules rts
     on tr.Id = rts.TaskResourceId left join
     TaskTimeSheets tts
     on rts.Id = tts.ResourceTaskScheduleId and
        cast(tts.CheckIn as date) >= @StartDate and
        cast(tts.CheckIn as date) <= @EndDate
where ((@EmployeeId is null) or 
       (e.Id in (select splitdata from dbo.SplitEmployeeIds(@EmployeeId, ','))))

【讨论】:

它现在给了我正确的结果,谢谢 Gordon-Linoff

以上是关于SQL左连接不包括左表中的所有记录的主要内容,如果未能解决你的问题,请参考以下文章

mysql左连接右连接(查询两张表不同的数据)

mysql左连接右连接(查询两张表不同的数据)

左外连接和右外连接的区别

外连接查询

左连接 ,右连接,内连接和全外连接的4者区别

sql中的join使用