Reputation: 4763
I have two tables:
Request:
RequestID | Msg
----------------
5 | abc
6 | def
7 | ghi
8 | jkl
RequestStatus:
RequestStatusID | RequestID |StatusID
-------------------------------------
1 5 1
2 8 2
RequestStatus
I need all the records from table Request
except when StatusID = 2
. (requestID=8
should be filter-out)
I am using LEFT OUTER JOIN
to recieve the records from table Request
but when I am adding Where clause (Where StatusID = 1)
of course it does not work.
Upvotes: 12
Views: 48108
Reputation: 351
In SQL Server 2017 you can put AND after ON in this way
SELECT * FROM Request
LEFT OUTER JOIN RequestStatus ON Request.RequestID = RequestStatus.RequestID
AND RequestStatus.StatusID <> 2
WHERE Request.RequestID IS NOT NULL
Upvotes: 4
Reputation: 38023
This answer assumes you just want the RequestId & Msg from the Request Table where there is not a record in the RequestStatus table with that RequestId and a StatusId of 2.
You won't get extra records for Requests with multiple RequestStatus records using this query either (vs Left join).
Using the not exists clause is faster than Except, Not In, Outer Apply, etc in this article by Aaron Bertrand - Should I use NOT IN, OUTER APPLY, LEFT OUTER JOIN, EXCEPT, or NOT EXISTS?
select r.RequestId, r.Msg
from Request r
where not exists (
select 1
from RequestStatus rs
where rs.StatusId = 2
and rs.RequestId = r.RequestId
)
Upvotes: 0
Reputation: 124
You need use an NOT IN Query Statement like this
Select *
From Request
Where RequestID not in
(Select RequestID
From RequestStatus
Where StatusID = 2)
or
Select *
From Request r
left join requestStatus rs on r.requestID = rs.requestID
Where r.RequestID not in
(Select RequestID
From RequestStatus
Where StatusID = 2)
Upvotes: 1
Reputation: 8693
Move the constraint to your on clause.
select *
from request r
left join requestStatus rs
on r.requestID = rs.requestID
--and status_id = 1
and status_id <> 2
What's happening to you is that the outer join is performed first. Any rows coming from the outer join that don't have matches will have nulls in all the columns. Then your where clause is applied, but since 1 <> null, it's not going to work like you want it to.
EDIT: Changed on clause based on Piyush's comment.
Upvotes: 22
Reputation: 2607
The answer is pretty simple, use left join but filter on the rows that have StatusId different than 2, like so:
select *
from request r
left join requestStatus rs
on r.requestID = rs.requestID
where rs.StatusId <> 2 or rs.StatusId IS NULL
EDIT: added or rs.StatusId IS NULL additional condition to also include rows in requestStatus table that don't have a match in request table.
Upvotes: 1
Reputation: 8487
Try this
SELECT *
FROM Request R
LEFT JOIN RequestStatus RS ON R.RequestID = RS.RequestID
WHERE RS.StatusID <> 2 OR RS.RequestID IS NULL
Upvotes: 3