我继承了一个使用左连接的查询。查询正在执行的操作之一是删除任何已存档的记录,即存档=' 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&#39 ;.我认为将过滤器与"放在"上会出现问题。是它会返回一个记录,其中c.archived =' N'并在归档字段中放置一个null,这是不正确的:
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为null的记录。
我只是想把归档的记录带回来&lt;&gt; &#39; Y&#39;,包括字段为空的那些。
要清楚,这就是表中记录的样子:
FirstName EntityID Archived
John 55 Y
Tom 56 NULL
Rob 57 N
在这种情况下,我希望返回的记录如下:
Tom 56 NULL
Rob 57 N
John将被淘汰,因为Archived =&#39; Y。&#39;
还有其他办法吗?
答案 0 :(得分:0)
如果我理解正确,您希望在where
子句中使用另一个字段进行过滤:
select firstname, entityid, committeeid -- this will return an error on committeeid
from Pract P left join
Committee C
on P.commiteeid = C.committeeid and
(c.archived <> 'Y' or c.archived is null)
where c.committeeid is not null;
您也可以更轻松地使用exists
执行此操作:
select p.*
from Pract P
where not exists (select 1
from Committee C
where P.commiteeid = C.committeeid and
c.archived = 'Y'
);
这会自动处理NULL
值。
答案 1 :(得分:0)
我相信你正在寻找这个版本。您只需从拥有的内容开始,然后修改连接条件以覆盖不等于Y且值为NULL的值。
select firstname, entityid, committeeid
from Pract P
left join Committee C
on P.commiteeid = C.committeeid
and (c.archived <> 'Y' OR c.archived IS NULL)
然后,如果您只需要在commitee表中有记录的项目。你把它放在WHERE子句中。
WHERE P.commiteeeid = C.commiteeid
但它只是模仿INNER JOIN。
比较NULL的问题是您不能使用&lt;&gt;测试NULL值。如果您想要具有NULL值的记录,则必须明确地测试IS NULL
。
因此,您更新的查询将如下所示:
select P.firstname, E.entityid, C.committeeid, L.locationname
from Pract P
left join Committee C
on P.commiteeid = C.committeeid
and (c.archived <> 'Y' OR c.archived IS NULL)
left join Entity E
on P.entityid = E.EntityID
and (e.archived <> 'Y' OR e.archived IS NULL)
left join Location L
on E.location = L.location
and (l.archived <> 'Y' OR l.archived IS NULL)
如果你只有价值观&#39; Y&#39; &#39; N&#39;和NULL,那么你也可以使用
and (c.archived = 'N' OR c.archived IS NULL)
为了确保我们彼此了解,这里是您查询的最小示例
create table Pract (firstname varchar(20), cid int)
create table comt ( cid int, archived varchar(1) )
insert into Pract values ('Tom',1),('Adam',2),('Mark',3),('Bob',4)
insert into comt values (1,'Y'), (2,'N'), (3,NULL)
-
select firstname, P.cid, C.cid, C.archived
from Pract P
LEFT join comt C
on P.cid = C.cid
and (c.archived <> 'Y' OR c.archived IS NULL)
结果
firstname cid cid archived
1 Tom 1 NULL NULL
2 Adam 2 2 N
3 Mark 3 3 NULL
4 Bob 4 NULL NULL
或使用INNER JOIN
select firstname, P.cid, C.cid, C.archived
from Pract P
INNER join comt C
on P.cid = C.cid
and (c.archived <> 'Y' OR c.archived IS NULL)
结果
firstname cid cid archived
1 Adam 2 2 N
2 Mark 3 3 NULL
答案 2 :(得分:-1)
解决方案取决于您希望如何处理左连接中的NULL值。如果NULL表示不存档,则
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' OR c.archived IS null)
and (e.archived = 'N' OR e.archived IS null)
and (l.archived = 'N' OR l.archived IS NULL)