我们有一个大型数据库,并从旧架构中导入旧的归档数据。我们已经根据新旧数据(A和B)创建了两个查询,并且想要标记'具有不同值以供审阅的字段。
我们设置了第三个查询,并手动匹配字段,如下所示:
CREATE VIEW vuAB_COMPARISON AS
SELECT
A.1
,B.1
,A.2
,B.2
,A.3
,B.3
...
...
...
,CASE
WHEN A.PK = B.PK
THEN 'RecordMatch'
WHEN A.PK <> B.PK
THEN 'RecordNoMatch'
END AS ComparisonCheck
FROM Table A
INNER JOIN Table B
ON A.PK = B.PK
我们要做的是将所有不匹配的字段附加到ComparisonCheck列。例如,如果A.1&lt;&gt; B.1,那么ComparisonCheck列将是&#39; RecordMatch; Field1_NoMatch&#39;
类似地,如果A.1&lt;&gt; B.1和A.2&lt;&gt; B.2然后,ComparisonCheck列将是&#39; RecordMatch; Field1_NoMatch; Field2_NoMatch&#39;等
我能想到的唯一方法是使用复杂的嵌套case语句。然而,有几十个字段要匹配,所以这将是tedius。
有更好的解决方案吗?我也考虑过将其分成两个查询,但我不确定是否让我更接近解决方案。
注意我已经简化了一些事情,因为实际上连接使用多个字段,而不是来自查询A / B的所有记录都匹配,这就是为什么设置CASE语句的原因。
答案 0 :(得分:0)
只是一个通用表比较脚本集:
将记录记录在a中,但不记录在b
中Select * from tablea a left join tableb b on b.pk = a.pk where b.pk is null
简单的逻辑,当pk在tablea中而不是b时,左连接产生空值,其中b.pk为null,所有都在a中。
将表格反转为b而不是a:
Select * from tableb b left join tablea a on b.pk = a.pk where a.pk is null
相同的逻辑,只是反转哪个表是第一个和空检查。从技术上讲,您可以使用右连接,而不是在from子句中更改哪个表是第一个
以及表之间的差异:
select a.*,b.* from tablea a inner join tableb b on a.pk = b.pk
where a.col1 <> b.col1 or a.col2 <> col2 or a.col3 <> a.col3 or etc...
这将只列出表之间不同的所有行。不幸的是,你需要在where子句中输入每一列。要将其更改为标记:
select a.pk, case when c.pk is not null then "no match' else 'match found' end
from tablea a
inner join tableb b on a.pk = b.pk
left join ( select a.pk from tablea a inner join tableb b on a.pk = b.pk
where a.col1 <> b.col1 or a.col2 <> col2 or a.col3 <> a.col3 or etc...) c
on a.pk = c.pk
逻辑正在使用子查询来挑选出在子查询中存在差异的所有PK,并从tablea继续加入它。如果c.pk为null,那么它不在子查询中并且行是相同的,如果c.pk不为null则行中存在差异...一个简单的case语句将其更改为标志。
答案 1 :(得分:0)
假设您有两张表:
create table t1 (id int, c1 int, c2 int, c3 int);
create table t2 (id int, c1 int, c2 int, c3 int);
insert into t1 values(0,0,0,0);
insert into t1 values(1,1,1,1);
insert into t1 values(2,2,2,2);
insert into t1 values(3,3,3,3);
--insert into t1 values(4,null,3,3);
--insert into t1 values(5,null,3,3);
insert into t1 values(6,3,3,3); --t2's missing record
insert into t2 values(0,0,0,0); --match
insert into t2 values(1,1,2,1); --c2 mismatch
insert into t2 values(2,2,3,3); --c2,c3 mismatch
insert into t2 values(3,2,2,2); --all mismatch
--insert into t2 values(4,null,3,3);
--insert into t2 values(5,3,null,3);
insert into t2 values(7,2,2,2); --t1's missing record
with
vt1 as
(select id, c_name , v1
from t1
unpivot (v1 for c_name in ([c1],[c2],[c3]) ) as t),
vt2 as
(select id, c_name , v2
from t2
unpivot (v2 for c_name in ([c1],[c2],[c3]) ) as t)
select distinct coalesce(vt1.id,vt2.id) as id
,case when vt1.id is null and vt2.id is not null
then 'RecordT1Missing'
when vt2.id is null and not vt1.id is null
then 'RecordT2Missing'
else 'RecordMatch' end as RecordMatchType
,case when v1<>v2 then vt1.c_name + '_NoMatch'
else '' end as ColumnMathType
from vt1
full outer join vt2
on vt1.id=vt2.id and vt1.c_name = vt2.c_name
;
这是输出,而不是问题中描述的格式,但有很多方法可以转回其他可读格式,可以留给OP工作:
ID RECORDMATCHTYPE COLUMNMATHTYPE
0 RecordMatch
1 RecordMatch
1 RecordMatch c2_NoMatch
2 RecordMatch
2 RecordMatch c2_NoMatch
2 RecordMatch c3_NoMatch
3 RecordMatch c1_NoMatch
3 RecordMatch c2_NoMatch
3 RecordMatch c3_NoMatch
6 RecordT2Missing
7 RecordT1Missing
使用@ ErikE的帮助,使用CROSS APPLY可以更轻松地处理空值。
with
vt1 as
(select id, c_name , v1
from t1
CROSS APPLY (VALUES ('c1',c1),('c2',c2),('c3',c3))
CrossApplied (c_name, v1) ),
vt2 as
(select id, c_name , v2
from t2
CROSS APPLY (VALUES ('c1',c1),('c2',c2),('c3',c3))
CrossApplied (c_name, v2) )
select distinct coalesce(vt1.id,vt2.id) as id
,case when vt1.id is null and vt2.id is not null
then 'RecordT1Missing'
when vt2.id is null and not vt1.id is null
then 'RecordT2Missing'
else 'RecordMatch' end as RecordMatchType
,case when v1<>v2 then vt1.c_name + '_NoMatch'
when v1 is null and v2 is not null and vt1.id is not null then vt1.c_name + '_T1Missing'
when v2 is null and v1 is not null and vt2.id is not null then vt1.c_name + '_T2Missing'
else '' end as ColumnMathType
from vt1
full outer join vt2
on vt1.id=vt2.id and vt1.c_name = vt2.c_name
;
如果这些数据具有空值,将得到以下结果:
ID RECORDMATCHTYPE COLUMNMATHTYPE
0 RecordMatch
1 RecordMatch
1 RecordMatch c2_NoMatch
2 RecordMatch
2 RecordMatch c2_NoMatch
2 RecordMatch c3_NoMatch
3 RecordMatch c1_NoMatch
3 RecordMatch c2_NoMatch
3 RecordMatch c3_NoMatch
4 RecordMatch
5 RecordMatch
5 RecordMatch c1_T1Missing
5 RecordMatch c2_T2Missing
6 RecordT2Missing
7 RecordT1Missing
它可以找出哪个列和ID为5的表中缺少的数据。