我最近不得不解决这个问题,发现我过去多次需要这些信息所以我想我会发布它。假设下面的表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)
)
答案 0 :(得分:2)
UNION将删除重复项,因此只需将两者联合起来,然后搜索包含多个条目的任何内容。将“代码”作为主键,您可以说:
编辑0:修改为包含PK字段本身的差异
编辑1:如果您在现实生活中使用它,请务必列出实际的列名称。不要使用dot-star,因为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)
答案 1 :(得分:0)
我会在第二个union
中使用一个小变体:
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中)。
答案 2 :(得分:0)
您还可以在FULL OUTER JOIN
列上使用CASE ... END
和diff_type
语句以及querying 2 tables with the same spec for the differences中提到的where
条款
这可能会在一个查询中实现相同的结果。