2008-08-27 82 views
1

我最近不得不解决这个问题,并发现我过去需要这个信息很多次,所以我想我会发布它。假设下面的表格def,你将如何编写一个查询来查找两者之间的所有差异?查询2个表格的差异相同规格

表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

我会用一个小的变化在第二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中)。

3

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)