当不存在行时,LEFT JOIN 不返回 null

EJF*_*EJF -1 sql sql-server join left-join

我正在使用 2 个表:1 个表处理一组人的基本人口统计数据,1 个表处理已完成的活动。我需要做的是从人口统计表中提取所有结果(所有人),然后显示在给定时间范围内完成某种类型活动的任何人的活动信息(给定的人也可能完成了多项活动)在那个时间范围内)。如果某人尚未完成任何指定的活动,我仍然希望他们在列表中可见。我希望结果如下所示:

PersonID  Name           DateOfBirth   ActivityDate   ActivityType
---------------------------------------------------------------------
1001      John Smith     01/01/1990    10/18/2022     Painting
1002      Jane Doe       12/31/1980    NULL           NULL
1003      Bob Brown      07/04/1995    10/17/2022     Reading
1003      Bob Brown      07/04/1995    09/09/2022     Painting
1004      Mike Jones     03/24/1984    NULL           NULL
1005      Ann Green      11/30/1988    08/29/2022     Writing
1006      Sally Black    05/15/1999    NULL           NULL
Run Code Online (Sandbox Code Playgroud)

看起来这应该是LEFT JOIN两个表之间非常简单的查询:

SELECT DISTINCT
    d.PersonID,
    d.Name
    d.DateOfBirth,
    a.ActivityDate
    a.ActivityType
FROM Demographics d
LEFT JOIN Activity a ON d.PersonID = a.PersonID
WHERE ActivityDate BETWEEN DATEADD(yy,-1,GETDATE()) AND GETDATE()
    AND ActivityType IN ('Painting','Reading','Writing')
ORDER BY d.PersonID, a.ActivityDate DESC
Run Code Online (Sandbox Code Playgroud)

NULL但是,当我运行此查询时,我仅获得实际完成活动的人员的结果(即,在我的示例中缺少结果的人员)。

PersonID  Name           DateOfBirth   ActivityDate   ActivityType
---------------------------------------------------------------------
1001      John Smith     01/01/1990    10/18/2022     Painting
1003      Bob Brown      07/04/1995    10/17/2022     Reading
1003      Bob Brown      07/04/1995    09/09/2022     Painting
1005      Ann Green      11/30/1988    08/29/2022     Writing
Run Code Online (Sandbox Code Playgroud)

再次,我想显示人口统计表中的所有人员,然后显示已完成活动的人员的指定活动。

我的加入有问题吗?这是LEFT JOIN正确的方法吗?

Dal*_*e K 5

您的WHERE子句完全基于左连接 ( Activity) 表,并且您不允许NULL在子句中的任何位置使用值WHERE。因此,联接正在工作,但您正在过滤掉没有活动的任何行。

要纠正此问题,请更改

WHERE ActivityDate BETWEEN DATEADD(yy,-1,GETDATE()) AND GETDATE()
    AND ActivityType IN ('Painting','Reading','Writing')
Run Code Online (Sandbox Code Playgroud)

WHERE a.PersonId IS NULL 
OR (
    ActivityDate BETWEEN DATEADD(yy,-1,GETDATE()) AND GETDATE()
    AND ActivityType IN ('Painting','Reading','Writing')
)
Run Code Online (Sandbox Code Playgroud)