Reputation: 632
I have a query that identifies orphaned rows in one table after joining it to another. The query I have for selecting the rows that need to be deleted works fine, and properly selects the rows that need to be deleted:
select fl.Request_ID as Check_RID,
fl.J_Number as Check_JID,
rh.request_ID,
rh.J_Number
from Route_Legs_Route_Header rh
left join Request_Route_Legs fl on fl.Request_ID = rh.Request_ID AND fl.J_Number = rh.J_Number
where rh.Route_ID <> 0
AND fl.Request_ID is null
My question is, now that I've selected which rows need to be deleted, how do I use this join to actually delete the rows from Route_Legs_Route_Header
?
Upvotes: 1
Views: 459
Reputation: 67301
I prefer an updatable cte in such cases:
First I create a mockup scenario to simulate your issue:
DECLARE @tblParent TABLE(ID INT IDENTITY,SomeValue VARCHAR(100));
INSERT INTO @tblParent VALUES('Row 1'),('Row 2');
DECLARE @tblChildren TABLE(ID INT IDENTITY, ParentID INT,SomeValue VARCHAR(100));
INSERT INTO @tblChildren VALUES(1,'Child 1.1'),(1,'Child 1.2')
,(2,'Child 2.1')
,(3,'Orphan');
--This query is - in principles - your approach:
--Add the table alias ch
to the *
to reduce the set on rows solely from @tblChildren
.
SELECT *
FROM @tblChildren ch
LEFT JOIN @tblParent p ON p.ID=ch.ParentID
WHERE p.ID IS NULL;
--This query is - at least for me - easier to read and does the same:
SELECT * FROM @tblChildren ch
WHERE NOT EXISTS(SELECT 1 FROM @tblParent p WHERE p.ID=ch.ParentID);
--We can place the last query into a cte's body and delete its resultset:
WITH cte AS
(
SELECT * FROM @tblChildren ch
WHERE NOT EXISTS(SELECT 1 FROM @tblParent p WHERE p.ID=ch.ParentID)
)
DELETE FROM cte;
--Check it out, the orphan is gone:
SELECT * FROM @tblChildren ch
WHERE NOT EXISTS(SELECT 1 FROM @tblParent p WHERE p.ID=ch.ParentID);
Upvotes: 0
Reputation: 10264
you should write the query as:
DELETE FROM rh
FROM Route_Legs_Route_Header AS rh
left join Request_Route_Legs fl on fl.Request_ID = rh.Request_ID
AND fl.J_Number = rh.J_Number
where rh.Route_ID <> 0
AND fl.Request_ID is null
The From
clause with the join operator will be evaluated first. Then the Delete
clause will delete the rows from rh
alias i.e. the table from the join Route_Legs_Route_Header
.
Hope this helps!!
Upvotes: 0
Reputation: 222442
In SQL Server, you can delete from a table alias. This comes handy when you already have a working query, like you do:
delete rh
from Route_Legs_Route_Header rh
left join Request_Route_Legs fl
on fl.Request_ID = rh.Request_ID and fl.J_Number = rh.J_Number
where rh.Route_ID <> 0 and fl.Request_ID is null
Upvotes: 3
Reputation: 7960
I'd use a temptable if I were you like below:
select fl.Request_ID as Check_RID,
fl.J_Number as Check_JID,
rh.request_ID,
rh.J_Number
INTO #RowsToDelete
from Route_Legs_Route_Header rh
left join Request_Route_Legs fl on fl.Request_ID = rh.Request_ID AND fl.J_Number = rh.J_Number
where rh.Route_ID <> 0
AND fl.Request_ID is null
DELETE FROM Route_Legs_Route_Header
WHERE request_ID in (Select Request_ID from #temp)
Upvotes: 0