检测同一个表的两个版本之间的差异

时间:2014-08-05 15:50:26

标签: sql rows difference

我正在寻找一种方法来检测同一个表的两个版本之间的差异。 让我们说我在两个不同的日子创建了一个活动表的副本:

第1天:

CREATE TABLE table_1 AS SELECT * FROM table

第2天:

CREATE TABLE table_2 AS SELECT * FROM table 

该方法应标识在第1天和第2天之间添加,删除或更新的所有行; 如果可能,该方法不应使用特定于RDBMS的功能;

注意:将表格的内容导出为文本文件并比较文本文件很好,但我想要一个特定于SQL的方法。

示例:

create table table_1 
(
 col1 integer,
 col2 char(10)
);
create table table_2
(
 col1 integer,
 col2 char(10)
);    
insert into table_1 values ( 1, 'One' );
insert into table_1 values ( 2, 'Two' );
insert into table_1 values ( 3, 'Three' );
insert into table_2 values ( 1, 'One' );
insert into table_2 values ( 2, 'TWO' );
insert into table_2 values ( 4, 'Four' );

table_1和table_2之间的差异:

  • 已添加:行(4,'四')
  • 已删除:行(3,'三')
  • 更新:第(2,'两个')更新为(2,' TWO')

3 个答案:

答案 0 :(得分:0)

如果你想要两个方向的差异。我假设你有id,因为你提到"更新"你需要一种方法来识别同一行。这是union all方法:

select t.id,
       (case when sum(case when which = 't2' then 1 else 0 end) = 0
             then 'InTable1-only'
             when sum(case when which = 't1' then 1 else 0 end) = 0
             then 'InTable2-only'
             when max(col1) <> min(col1) or max(col2) = min(col2) or . . .
             then 'Different'
             else 'Same'
        end)             
from ((select 'table1' as which, t1.*
       from table_1 t1
      ) union all
      (select 'table2', t2.*
       from table_2 t2
      )
     ) t;

这是标准的SQL。你可以过滤掉&#34;相同的&#34;记录,如果你想。

这假设所有列都具有非NULL值,并且具有给定id的行在每个表中最多出现一次。

答案 1 :(得分:0)

我想我找到了答案 - 可以使用此SQL语句来构建差异列表:

注意:“col1,col2”列表必须包含表格中的所有列

SELECT
MIN(table_name) as table_name, col1, col2
FROM
(
   SELECT
   'Table_1' as table_name, col1, col2
   FROM Table_1 A
   UNION ALL
   SELECT
   'Table_2' as table_name, col1, col2
   FROM Table_2 B
)
tmp
GROUP BY col1, col2
HAVING COUNT(*) = 1

+------------+------+------------+
| table_name | col1 |    col2    |
+------------+------+------------+
| Table_2    |    2 | TWO        |
| Table_1    |    2 | Two        |
| Table_1    |    3 | Three      |
| Table_2    |    4 | Four       |
+------------+------+------------+

在问题中引用的示例中,

  • 表2中的行(4,'四');判决行“已添加
  • 表1中的行(3,'Three');判决行“已删除
  • 行(2,'Two')仅出现在table_1中;行(2,'TWO')仅出现在table_2中;如果col1是主键,则判定“已更新

答案 2 :(得分:0)

如果您可以认为该表具有唯一的主键,那么以下SQL语句最后会创建三个视图,其中包含已更改的ID,新ID和已删除的ID。

在以下&#34; tbl1 &#34;是旧版本&#34; tbl2 &#34;是新版本(相同的架构)。假设表格中的主键名为&#34; _id &#34;。 中间视图&#34; _NewChanged &#34;将在新版本的表格中包含新的和已更改的ID以及视图&#34; _RemovedChanged &#34;将包含新版本中已删除和已更改的ID。

生成增量SQL语句只需要以编程方式循环各个视图以创建增量集并执行删除,更新,插入将旧版本转换为新版本的状态。

解决方案有三点需要注意:

  • 它不会确切地指出哪些列已更改
  • 假设架构在表格的旧版本和新版本中相同
  • 它假定SQL语句INTERSECT和EXCEPT可用

为了保持代码简洁,没有插入评论。

drop view if exists _NewChanged;
drop view if exists _RemovedChanged;

create view _NewChanged as 
select * from tbl2
except
select * from tbl1;

create view _RemovedChanged as 
select * from tbl1
except
select * from tbl2;

drop view if exists changed;
drop view if exists new;
drop view if exists deleted;

create view changed as
select _id from _NewChanged
intersect
select _id from _RemovedChanged;

create view new as
select _id from _NewChanged
except
select _id from _RemovedChanged;

create view deleted as
select _id from _RemovedChanged
except
select _id from _NewChanged;