如何在一个查询中从两个表中查找丢失的记录?

时间:2019-01-23 14:40:23

标签: sql

我有两个表itemsitems_archive都由于存储过程错误而丢失了信息。

我有一个表items_restored,我从文本备份中恢复了该表,其中包含许多不在itemsitems_archive中的项目,我需要最终插入items_restored已进入items_archive

我能够很容易地找到一个比较结果,

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;

这给了我items_restored中没有items_archive中的id的列表,但是问题是其中某些ID可能出现在items中。如果我在items而不是items_archive上运行上述查询,则会发生相同的问题,我看到丢失的内容,但很有可能丢失的ID在items_archive中。

我最终需要运行INSERT,我认为如果我根据这些查询来做一顿饭,那么很有可能最终要插入重复的记录,而这是我想要避免的。

我如何制作查询以同时检查itemsitems_archive ID并与我的items_restored ID进行比较,以便避免重复?

编辑:我最终选择了全部合并,这是我在LEFT JOIN之后做的。谢谢大家。

2 个答案:

答案 0 :(得分:0)

您可以重复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;

我认为NOT EXISTS是表达逻辑的一种更简洁的方法:

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);

答案 1 :(得分:0)

我建议合并语句。您将能够比较这些数据之间的所有数据,但是可以根据匹配,不匹配等条件设置条件,这可以减轻您指出的某些问题。但是,如果我记得的话,合并仅在SQL Server 2008+中可用,因此语法可能不可用,因为您仅标记了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.*;

为简洁起见,我确实精简了代码,因为我不确定特定的列名,但是您也可以结合输出操作来指示查询容易完成的工作。但是,在同类表之间合并数据的好方法。

您提到找到丢失的数据,我的想法是,如果不存在匹配项,则会创建该匹配项并将其扔到输出日志中。