I have two tables, items
and items_archive
which are both missing information due to a faulty stored procedure.
I have a table items_restored
that I restored from text backups that contains many items that are not in items
or items_archive
and I need to end up inserting what items_restored
has into items_archive
.
I am able to find a one off comparison pretty easily, doing
SELECT ir.id, i_a.id
FROM items_restord as ir
LEFT JOIN items_archive as i_a ON ir.id = i_a.id
WHERE i_a.id IS NULL;
This gives me a list of id's that I have in items_restored
that are not in items_archive
, however the problem is that some of them MAY be present in items
. The same issue happens if I run the above query on items
instead of items_archive
, I see whats missing but it's very possible the missing id is in items_archive
.
I need to run an INSERT
eventually and I think if I do it piece meal based on these queries, there's a good chance I'm going to end up inserting duplicate records which I want to avoid.
How can I craft the query to check both items
and items_archive
id's to compare to my items_restored
id's so that I can avoid the duplication?
Edit: I ended up going with union all, which I did right after the LEFT JOIN
. Thanks everyone.
You can repeat the LEFT JOIN
:
SELECT ir.id --, i_a.id -- this is always NULL so why select it?
FROM items_restord ir LEFT JOIN
items_archive i_a
ON ir.id = i_a.id LEFT JOIN
items i
ON ir.id = i.id
WHERE i_a.id IS NULL AND i.id IS NULL;
I think NOT EXISTS
is a cleaner way to express the logic:
select ir.*
from items_restord ir
where not exists (select 1 from items_archive i_a where ir.id = i_a.id) and
not exists (select 1 from items i where ir.id = i.id);
I would recommend the merge statement. You'll be able to compare all of the data between those, but set conditions based on matched, no match, etc. which would alleviate some of the issues you denoted. However, merge is only available in SQL Server 2008+ if I recall, so the syntax may not be available since you tagged only SQL.
MERGE INTO items_archive AS Target
USING (
SELECT ...
FROM items_restore AS Source (
...
)
)
ON (target.Id = source.Id)
WHEN MATCHED THEN UPDATE SET
...
WHEN NOT MATCHED BY TARGET THEN INSERT (
...
) VALUES (
...
)
WHEN NOT MATCHED BY SOURCE THEN DELETE
OUTPUT $action, Inserted.*, Deleted.*;
I did condense code for brevity since I am not sure of specific column names, but you can also couple with an output action to indicate what the query is doing easily. But good way to merge data between tables of like sorts.
You mention finding the missing data, my thought was if a match does not exists it would be created and thrown into the output log.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.