2008-08-27 80 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)