问题描述
我有两个具有相同架构/结构的表。两个表都可以包含另一个表中不存在的数据。
我需要找出它们之间的差异并将结果放入一个文件中。
ID 列是键,但可以有多个条目。
结果应该类似于差异表其中表 B 中表 A 中的行或表 A 中表 B 中的行的精确匹配应被忽略,所有其他应被捕获。。 >
我想到了使用 COALESCE 然后进行比较。
下面的示例表,当列数更多(10 列)时,是否有更好更快的方法来执行此操作?
解决方法
通常可以使用 MINUS
set operator + UNION ALL
解决:
(select * from t1
minus
select * from t2)
UNION ALL
(select * from t2
minus
select * from t1)
但问题是 Hive 不支持 MINUS 或 EXCEPT 运算符。
您可以使用左连接获取在一个表中不匹配的记录,并使用 UNION ALL 与另一个表中不匹配的记录。
select * from
(
select a.id,a.col1,a.col2,a.col3,'table_a' as src
from table_a
left join table_b
on a.id=b.id
and a.col1=b.col1
and a.col2=b.col2
and a.col3=b.col3
where b.id is null --not matching in table_b
UNION ALL --You may want to use UNION instead of UNION All to remove duplicates
select b.id,b.col1,b.col2,b.col3,'table_b' as src
from table_b
left join table_a
on a.id=b.id
and a.col1=b.col1
and a.col2=b.col2
and a.col3=b.col3
where a.id is null --not matching in table_a
) s
order by id,src; --order to put similar records together
我添加了 src
列,因此您可以轻松识别该记录属于哪个表,如果不需要,您可以将其删除。
使用相关的 NOT EXISTS 而不是 LEFT JOIN 也可以做到同样的事情,但它在 Hive 中产生完全相同的计划,性能没有差异。
另外,如果您的表可以包含 NULL 并且您也想匹配它们,
在连接 NVL()
条件中使用 ON
函数,例如像这样:
NVL(a.col3,'NULL')=NVL(b.col3,'NULL')
-- 对于数字列,使用一些常量,如 -999999
而不是 'NULL'
。