【发布时间】:2017-06-28 19:15:21
【问题描述】:
我继承了一个使用左连接的查询。查询正在做的一件事是删除所有归档记录,即归档 = 'Y'。这是查询的样子:
select P.firstname, E.entityid, C.committeeid, L.locationname
from Pract P
left join Committee C
on P.commiteeid = C.committeeid
and c.archived = 'N'
left join Entity E
on P.entityid = E.EntityID
and e.archived = 'N'
left join Location L
on E.location = L.location
and l.archived = 'N'
结果应该只返回归档 'Y' 的记录。我认为将过滤器设置为“on”的一个问题是它会返回一条记录,其中 c.archived = 'N' 并在归档字段中放置一个空值,这是不正确的:
FirstName EntityID CommitteeId
John 55 null
如果 c.archived = 'Y' 则记录不应显示。
我认为归档的过滤器应该在 where 子句中,像这样:
select firstname, entityid, committeeid
from Pract P
left join Committee C
on P.commiteeid = C.committeeid
left join Entity E
on P.entityid = E.entityid
left join Location L
on E.Locationid = L.locationid
where c.archived = 'N'
and e.archived = 'N'
and l.archived = 'N'
我发现的问题是,在某些情况下,委员会的存档字段为空(不是“Y”或“N”)。使用我的解决方案错误地消除了自 null 'N' 以来的记录。
如果我试试这个:
where c.archived <> 'Y'
它不起作用,我猜是因为 NULL 不会评估任何东西。
如果我试试这个:
where (c.archived = 'N' or c.archived is null)
它不起作用,因为它现在带回了由左连接引起的那些空记录。我不能用内连接替换左连接,因为这将排除 c.committeeid 为空的记录。
我只想带回归档'Y'的记录,包括那些字段为空的记录。
明确地说,表中的记录如下所示:
FirstName EntityID Archived
John 55 Y
Tom 56 NULL
Rob 57 N
在这种情况下,我希望返回的记录如下所示:
Tom 56 NULL
Rob 57 N
John 将被淘汰,因为 Archived = 'Y'。
还有其他方法吗?
【问题讨论】:
-
“我认为将过滤器设置为“on”的一个问题是它会返回一条记录,其中 c.archived = 'N' 并在归档字段中放置一个空值,这是不正确的。” 它完全按照它应该做的。您正在进行 left join 这意味着 left 表中的所有元素都应包含在结果中。由于在符合该过滤器的右表上找不到匹配项,因此您将获得这些列的空值。如果您只想要 right 表中匹配的元素,请执行 inner join。
-
我继承了这段代码,并试图让它正常工作。我相信原始开发人员没有以正确的方式编写此内容。如果“archived = 'N' 所以左连接不合适,我不希望返回记录。但如果表中的“归档”字段为 Null,我确实希望返回记录。我不能进行内部连接,因为有连接右侧表中的字段为空的实例。内部连接将消除这些。如果 C.committeeid 为空,我不能执行“on P.commiteeid = C.committeeid”。我只需要它返回记录“存档'Y'.
-
您能给我们展示示例数据和预期结果吗?我不清楚您要达到的目标。
-
@jackstraw22 我的解决方案将适用于您的示例数据。
标签: sql sql-server-2008 left-join