Sql server 带WHERE子句的Sql左外部联接

Sql server 带WHERE子句的Sql左外部联接,sql-server,Sql Server,我有两张桌子: 请求: 请求状态: 并非每个请求都有RequestStatus中的记录 我需要表请求中的所有记录,StatusID=2时除外。requestID=8应该被过滤掉 我使用LEFT-OUTER-JOIN从表请求接收记录,但是当我添加Where子句Where StatusID=1时,它当然不起作用。您需要使用这样的not IN查询语句 Select * From Request Where RequestID not in (Select RequestID F

我有两张桌子:

请求:

请求状态:

并非每个请求都有RequestStatus中的记录 我需要表请求中的所有记录,StatusID=2时除外。requestID=8应该被过滤掉


我使用LEFT-OUTER-JOIN从表请求接收记录,但是当我添加Where子句Where StatusID=1时,它当然不起作用。

您需要使用这样的not IN查询语句

Select * 
From Request 
Where RequestID not in 
    (Select RequestID 
    From RequestStatus 
    Where StatusID = 2)


答案很简单,使用left join,但对StatusId不同于2的行进行筛选,如下所示:

select *
from request r
left join requestStatus rs
on r.requestID = rs.requestID
where rs.StatusId <> 2 or rs.StatusId IS NULL

编辑:added或rs.StatusId为NULL附加条件,以包括requestStatus表中与request表中不匹配的行。

将约束移动到on子句中

select *
from request r
left join requestStatus rs
on r.requestID = rs.requestID
--and status_id = 1
and status_id <> 2
发生在您身上的是首先执行外部联接。来自外部联接但没有匹配项的任何行的所有列中都将有空值。然后应用where子句,但由于1为null,它不会像您希望的那样工作

编辑:根据皮尤斯的评论修改了子句。

试试这个

SELECT *
FROM Request R
  LEFT JOIN RequestStatus RS ON R.RequestID  =  RS.RequestID   
  WHERE RS.StatusID <> 2 OR RS.RequestID IS NULL
这个答案假设您只需要请求表中的RequestId&Msg,其中RequestStatus表中没有该RequestId和StatusId为2的记录

对于使用此查询的具有多个RequestStatus记录的请求,与Left join相比,您也不会获得额外的记录


使用not exists子句比本文中的Except、not In、EXTER Apply等更快

选择r.RequestId,r.Msg 从请求r 不存在的地方 选择1 来自状态请求者 其中rs.StatusId=2 和rs.RequestId=r.RequestId
在SQL Server 2017中,您可以通过这种方式打开和关闭

SELECT * FROM Request
LEFT OUTER JOIN RequestStatus ON Request.RequestID = RequestStatus.RequestID
AND RequestStatus.StatusID <> 2
WHERE Request.RequestID IS NOT NULL

@Andrew,我需要表请求中的所有记录,StatusID=2时除外。requestID=8应被过滤掉。。还需要说什么?这就是为什么我删除了我的boneheaded注释:但是,这个解决方案仍然会破坏外部连接:不是我的,但将外部表放在where子句中会强制只包含非空行,并根据该筛选器进行检查。实际上,这将使外部联接变成内部联接,并且不再返回OP想要的行。@Andrew,感谢您的评论和修改,这使我重新考虑where子句。刚刚编辑了答案。Andrew的答案比我的更清晰。在本文中使用not exists子句比Except、not In、EXTER Apply等更快。我认为OP需要除statusID=2之外的所有行,而不仅仅是1,它不会过滤掉statusID=2的行。仅移除右侧。在另一个例子中,这对我来说非常有效。伟大的思想也适用于PostgreSQL。谢谢
select *
from request r
left join requestStatus rs
on r.requestID = rs.requestID
--and status_id = 1
and status_id <> 2
SELECT *
FROM Request R
  LEFT JOIN RequestStatus RS ON R.RequestID  =  RS.RequestID   
  WHERE RS.StatusID <> 2 OR RS.RequestID IS NULL
SELECT * FROM Request
LEFT OUTER JOIN RequestStatus ON Request.RequestID = RequestStatus.RequestID
AND RequestStatus.StatusID <> 2
WHERE Request.RequestID IS NOT NULL