比较两个没有唯一键的表
Posted
技术标签:
【中文标题】比较两个没有唯一键的表【英文标题】:Comparing two tables that doesn't have unique key 【发布时间】:2016-11-25 12:53:11 【问题描述】:我需要比较两个表数据并检查哪些属性不匹配,表具有相同的表定义,但问题是我有一个唯一的键来比较。我尝试使用
CONCAT(CONCAT(CONCAT(table1.A, Table1.B))
=CONCAT(CONCAT(CONCAT(table2.A, Table2.B))
但仍然面临重复的行也尝试了 NVL 在几列上但没有工作
SELECT
UT.cat,
PD.cat
FROM
EM UT, EM_63 PD
WHERE
NVL(UT.cat, 1) = NVL(PD.cat, 1) AND
NVL(UT.AT_NUMBER, 1) = NVL(PD.AT_NUMBER, 1) AND
NVL(UT.OFFSET, 1) = NVL(PD.OFFSET, 1) AND
NVL(UT.PROD, 1) = NVL(PD.PROD, 1)
;
一个表有 34k 条记录,另一个表有 35k 条记录,但是如果我运行上面的查询,行数是 300 万。
表格中的列:
COUNTRY
CATEGORY
TYPE
DESCRIPTION
样本数据:
表 1:
COUNTRY CATEGORY TYPE DESCRIPTION
US C T1 In
IN A T2 OUT
B C T2 IN
Y C T1 INOUT
表2:
COUNTRY CATEGORY TYPE DESCRIPTION
US C T2 In
IN B T2 Out
Q C T2 IN
预期输出:
column Matched unmatched
COUNTRY 2 1
CATEGORY 2 1
TYPE 2 1
DESCRIPTION 3 0
【问题讨论】:
添加一些示例表数据和预期结果。 (以及格式化文本。) 为什么要三重连接? 请更新您添加数据样本的问题和预期结果 你可以使用这套:(A-B) U (B-A)
= (select * from A minus select * from B) union (select * from B minus select * from A)
@Varoo - 虽然 Cunning 的建议不会给你最有效的执行,但它们应该会给你正确的结果。您所说的“重复行”是什么意思 - UNION、INTERSECT 和 MINUS 消除了重复,因此您一定是错误地使用了“重复”这个词,或者您没有正确实施建议。
【参考方案1】:
在最一般的情况下(当您可能有重复的行,并且您想查看一个表中存在哪些行但另一个表中不存在时,以及两个表中可能存在哪些行,但该行在第一个表,但在另一个表中 5 次):
这是一个非常常见的问题,有一个已解决的“最佳解决方案”,出于某种原因,大多数人似乎仍然没有意识到这一点,尽管它是多年前在 AskTom 上开发的,并且已经被多次提出。
您不需要连接,不需要任何类型的唯一键,也不需要多次读取任一表。这个想法是添加两列以显示每行来自哪个表,执行 UNION ALL,然后 GROUP BY 除“源”列之外的所有列并显示每个表的计数。像这样的:
select count(t_1) as count_table_1, count(t_2) as count_table_2, col1, col2, ...
from (
select 'x' as t_1, null as t_2, col1, col2, ...
from table_1
union all
select null as t_1, 'x' as t_2, col1, col2, ...
from table_2
)
group by col1, col2, ...
having count(t_1) != count(t_2)
;
【讨论】:
感谢您的建议,但我们可以得到像 Columnname,matched count,unmatchedcount 这样的输出 @varoo - “匹配计数”是什么意思?您想按列执行此操作吗?我不确定这是否有意义。请发布一个小样本,说明结果应该是什么样子(不要担心如何实现)以及它的含义。 更新了样本数据【参考方案2】:从这个查询开始,检查这 4 列是否构成一个键。
select occ_total,occ_ut,occ_pd
,count(*) as records
from (select count (*) as occ_total
,count (case tab when 'UT' then 1 end) as occ_ut
,count (case tab when 'PD' then 1 end) as occ_pd
from select 'UT' as tab,cat,AT_NUMBER,OFFSET,PROD from EM
union all select 'PD' ,cat,AT_NUMBER,OFFSET,PROD from EM_63 PD
) t
group by cat,AT_NUMBER,OFFSET,PROD
) t
group by occ_total,occ_ut,occ_pd
order by records desc
;
选择“键”后,您可以使用以下查询查看属性的值
select count (*) as occ_total
,count (case tab when 'UT' then 1 end) as occ_ut
,count (case tab when 'PD' then 1 end) as occ_pd
,count (distinct att1) as cnt_dst_att1
,count (distinct att2) as cnt_dst_att2
,count (distinct att3) as cnt_dst_att3
,...
,listagg (case tab when 'UT' then att1 end) within group (order by att1) as att1_vals_ut
,listagg (case tab when 'PD' then att1 end) within group (order by att1) as att1_vals_pd
,listagg (case tab when 'UT' then att2 end) within group (order by att2) as att2_vals_ut
,listagg (case tab when 'PD' then att2 end) within group (order by att2) as att2_vals_pd
,listagg (case tab when 'UT' then att3 end) within group (order by att3) as att3_vals_ut
,listagg (case tab when 'PD' then att3 end) within group (order by att3) as att3_vals_pd
,...
from select 'UT' as tab,cat,AT_NUMBER,OFFSET,PROD,att1,att2,att3,... from E M
union all select 'PD' ,cat,AT_NUMBER,OFFSET,PROD,att1,att2,att3,... from EM_63 PD
) t
group by cat,AT_NUMBER,OFFSET,PROD
;
【讨论】:
【参考方案3】:CONCAT
的问题是,如果您的数据与此类似,您可能会得到无效匹配:
table1.A = '123'
table1.B = '456'
连接到:'123456'
table2.A = '12'
table2.B = '3456'
也连接到:'123456'
您必须单独比较字段:table1.A = table2.A AND table1.B = table2.B
【讨论】:
我试过比较 table1.A =table2.A ,但我也需要不同数据的 count(*)。以上是关于比较两个没有唯一键的表的主要内容,如果未能解决你的问题,请参考以下文章