查询具有相同规格的2个表之间的差异
时间:2020-03-05 18:44:03 来源:igfitidea点击:
我最近不得不解决这个问题,发现我过去多次需要此信息,所以我认为我会发布它。假设下表def,我们将如何编写查询以查找两者之间的所有差异?
表def:
CREATE TABLE feed_tbl ( code varchar(15), name varchar(40), status char(1), update char(1) CONSTRAINT feed_tbl_PK PRIMARY KEY (code) CREATE TABLE data_tbl ( code varchar(15), name varchar(40), status char(1), update char(1) CONSTRAINT data_tbl_PK PRIMARY KEY (code)
这是我的解决方案,作为使用三个由联合联接的查询的视图。指定的diff_type是记录需要更新的方式:从_data(2)删除,在_data(1)中更新或者添加到_data(0)中。
CREATE VIEW delta_vw AS ( SELECT feed_tbl.code, feed_tbl.name, feed_tbl.status, feed_tbl.update, 0 as diff_type FROM feed_tbl LEFT OUTER JOIN data_tbl ON feed_tbl.code = data_tbl.code WHERE (data_tbl.code IS NULL) UNION SELECT feed_tbl.code, feed_tbl.name, feed_tbl.status, feed_tbl.update, 1 as diff_type FROM data_tbl RIGHT OUTER JOIN feed_tbl ON data_tbl.code = feed_tbl.code where (feed_tbl.name <> data_tbl.name) OR (data_tbl.status <> feed_tbl.status) OR (data_tbl.update <> feed_tbl.update) UNION SELECT data_tbl.code, data_tbl.name, data_tbl.status, data_tbl.update, 2 as diff_type FROM feed_tbl LEFT OUTER JOIN data_tbl ON data_tbl.code = feed_tbl.code WHERE (feed_tbl.code IS NULL) )
解决方案
回答
我将在第二个"联合"中使用一个较小的变体:
where (ISNULL(feed_tbl.name, 'NONAME') <> ISNULL(data_tbl.name, 'NONAME')) OR (ISNULL(data_tbl.status, 'NOSTATUS') <> ISNULL(feed_tbl.status, 'NOSTATUS')) OR (ISNULL(data_tbl.update, '12/31/2039') <> ISNULL(feed_tbl.update, '12/31/2039'))
由于我从未理解的原因," NULL"不等于" NULL"(至少在SQL Server中)。
回答
我们还可以在diff_type
列上使用FULL OUTER JOIN
和CASE ... END
语句以及上述的where
子句来查询两个具有相同规范的表以查找差异
那可能会达到相同的结果,但是只需一次查询。
回答
UNION将删除重复项,因此仅将UNION一起删除,然后搜索具有多个条目的任何内容。给定"代码"作为主键,我们可以说:
编辑0:修改为在PK字段本身中包含差异
编辑1:如果我们在现实生活中使用此功能,请确保列出实际的列名。不要使用点星号,因为UNION操作要求结果集具有完全匹配的列。如果我们在其中一个表中添加/删除了列,则此示例将中断。
select dt.* from data_tbl dt ,( select code from ( select * from feed_tbl union select * from data_tbl ) group by code having count(*) > 1 ) diffs --"diffs" will return all differences *except* those in the primary key itself where diffs.code = dt.code union --plus the ones that are only in feed, but not in data select * from feed_tbl ft where not exists(select code from data_tbl dt where dt.code = ft.code) union --plus the ones that are only in data, but not in feed select * from data_tbl dt where not exists(select code from feed_tbl ft where ft.code = dt.code)