比较 HIVE 中两个表的相等性
Comparing two tables for equality in HIVE
我有两个表,table1 和 table2。每个都有相同的列:
key, c1, c2, c3
我想检查一下这些表是否彼此相等(它们具有相同的行)。到目前为止,我有这两个查询(<> = 在 HIVE 中不相等):
select count(*) from table1 t1
left outer join table2 t2
on t1.key=t2.key
where t2.key is null or t1.c1<>t2.c1 or t1.c2<>t2.c2 or t1.c3<>t2.c3
和
select count(*) from table1 t1
left outer join table2 t2
on t1.key=t2.key and t1.c1=t2.c1 and t1.c2=t2.c2 and t1.c3=t2.c3
where t2.key is null
所以我的想法是,如果返回零计数,则表是相同的。但是,第一个查询的计数为零,第二个查询的计数为非零。它们究竟有何不同?如果有更好的方法来检查这个当然让我知道。
如果要检查重复项 和 表具有完全相同的结构 和 表中没有重复项,那么你可以这样做:
select t.key, t.c1, t.c2, t.c3, count(*) as cnt
from ((select t1.*, 1 as which from table1 t1) union all
(select t2.*, 2 as which from table2 t2)
) t
group by t.key, t.c1, t.c2, t.c3
having cnt <> 2;
如有必要,您可以通过多种方式放宽第一段中的条件。
请注意,当列具有 NULL
值时,此版本也适用。这些可能会导致您的数据出现问题。
使用 MINUS
运算符:
SELECT count(*) FROM
(SELECT t1.c1, t1.c2, t1.c3 from table1 t1
MINUS
SELECT t2.c1, t2.c2, t2.c3 from table2 t2)
第一个排除 t1.c1、t1.c2、t1.c3、t2.c1、t2.c2 或 t2.c3 为空的行。这意味着您有效地进行了内部联接。
第二个将找到 t1 中存在但 t2 中不存在的行。
要同时查找存在于 t2 但不存在于 t1 中的行,您可以执行完全外部联接。以下SQL假设所有列都是NOT NULL
:
select count(*) from table1 t1
full outer join table2 t2
on t1.key=t2.key and t1.c1=t2.c1 and t1.c2=t2.c2 and t1.c3=t2.c3
where t1.key is null /* this condition matches rows that only exist in t2 */
or t2.key is null /* this condition matches rows that only exist in t1 */
另一种变体
select c1-c2 "different row counts"
, c1-c3 "mismatched rows"
from
( select count(*) c1 from table1)
,( select count(*) c2 from table2 )
,(select count(*) c3 from table1 t1, table2 t2
where t1.key= t2.key
and T1.c1=T2.c1 )
尝试使用 WITH 子句:
With cnt as(
select count(*) cn1 from table1
)
select 'X' from dual,cnt where cnt.cn1 = (select count(*) from table2);
我建议您不要使用任何 JOIN 来尝试比较表:
- 当表很大时(在 Hive 中通常是这种情况),这是一个相当昂贵的操作
- 当某些行/"join keys" 重复时可能会出现问题
(当数据在不同 clusters/datacenters/clouds 时,它也可能不切实际)。
相反,我认为最好使用校验和方法并比较两个表的校验和。
我开发了一个 Python 脚本,可以让您轻松进行此类比较,并在网络浏览器中查看差异:
https://github.com/bolcom/hive_compared_bq
希望对您有所帮助!
一个简单的解决方案是进行内部联接。假设我们有两个配置单元 table,即 table1 和 table2。 table 都有相同的列,即 col1、col2 和 col3。行数也应该相同。然后命令如下
**
select count(*) from table1
inner join table2
on table1.col1 = table2.col1
and table1.col2 = table2.col2
and table1.col3 = table2.col3 ;
**
如果输出值与 table1 和 table2 中的行数相同,则所有列都具有相同的值,但是如果输出计数小于某些数据这是不同的。
首先获取表 C1 和 C2 的计数。 C1 和 C2 应该相等。 C1和C2可以通过以下查询得到
select count(*) from table1
如果 C1 和 C2 不相等,则表不相同。
2:查找表 DC1 和 DC2 的非重复计数。 DC1 和 DC2 应该相等。可以使用以下查询找到不同记录的数量:
select count(*) from (select distinct * from table1)
如果 DC1 和 DC2 不相等,则表不相同。
3:现在获取对2张表进行联合得到的记录数。假设为 U。使用以下查询获取 2 个表的联合中的记录数:
SELECT count (*)
FROM
(SELECT *
FROM table1
UNION
SELECT *
FROM table2)
如果2个表的distinct count等于2个表union得到的记录数,就可以说2个表的数据是一样的。即 DC1 = U 和 DC2 = U
嗯,最好的办法是计算每个table的哈希和,然后比较哈希和。
所以无论它们有多少列,无论它们是什么数据类型,只要两者table具有相同的架构,就可以使用以下查询进行比较:
select sum(hash(*)) from t1;
select sum(hash(*)) from t2;
您只需要比较 return 个值。
我使用了 EXCEPT 语句并且有效。
select * from Original_table
EXCEPT
select * from Revised_table
将向我们显示原始 table 中未包含在修订版 table 中的所有行。
如果您的 table 已分区,您将必须提供分区谓词。
仅供参考,如果您使用 Presto 并通过 SQL 实验室进行查询,则不需要提供分区值。
我有两个表,table1 和 table2。每个都有相同的列:
key, c1, c2, c3
我想检查一下这些表是否彼此相等(它们具有相同的行)。到目前为止,我有这两个查询(<> = 在 HIVE 中不相等):
select count(*) from table1 t1
left outer join table2 t2
on t1.key=t2.key
where t2.key is null or t1.c1<>t2.c1 or t1.c2<>t2.c2 or t1.c3<>t2.c3
和
select count(*) from table1 t1
left outer join table2 t2
on t1.key=t2.key and t1.c1=t2.c1 and t1.c2=t2.c2 and t1.c3=t2.c3
where t2.key is null
所以我的想法是,如果返回零计数,则表是相同的。但是,第一个查询的计数为零,第二个查询的计数为非零。它们究竟有何不同?如果有更好的方法来检查这个当然让我知道。
如果要检查重复项 和 表具有完全相同的结构 和 表中没有重复项,那么你可以这样做:
select t.key, t.c1, t.c2, t.c3, count(*) as cnt
from ((select t1.*, 1 as which from table1 t1) union all
(select t2.*, 2 as which from table2 t2)
) t
group by t.key, t.c1, t.c2, t.c3
having cnt <> 2;
如有必要,您可以通过多种方式放宽第一段中的条件。
请注意,当列具有 NULL
值时,此版本也适用。这些可能会导致您的数据出现问题。
使用 MINUS
运算符:
SELECT count(*) FROM
(SELECT t1.c1, t1.c2, t1.c3 from table1 t1
MINUS
SELECT t2.c1, t2.c2, t2.c3 from table2 t2)
第一个排除 t1.c1、t1.c2、t1.c3、t2.c1、t2.c2 或 t2.c3 为空的行。这意味着您有效地进行了内部联接。
第二个将找到 t1 中存在但 t2 中不存在的行。
要同时查找存在于 t2 但不存在于 t1 中的行,您可以执行完全外部联接。以下SQL假设所有列都是NOT NULL
:
select count(*) from table1 t1
full outer join table2 t2
on t1.key=t2.key and t1.c1=t2.c1 and t1.c2=t2.c2 and t1.c3=t2.c3
where t1.key is null /* this condition matches rows that only exist in t2 */
or t2.key is null /* this condition matches rows that only exist in t1 */
另一种变体
select c1-c2 "different row counts"
, c1-c3 "mismatched rows"
from
( select count(*) c1 from table1)
,( select count(*) c2 from table2 )
,(select count(*) c3 from table1 t1, table2 t2
where t1.key= t2.key
and T1.c1=T2.c1 )
尝试使用 WITH 子句:
With cnt as(
select count(*) cn1 from table1
)
select 'X' from dual,cnt where cnt.cn1 = (select count(*) from table2);
我建议您不要使用任何 JOIN 来尝试比较表:
- 当表很大时(在 Hive 中通常是这种情况),这是一个相当昂贵的操作
- 当某些行/"join keys" 重复时可能会出现问题
(当数据在不同 clusters/datacenters/clouds 时,它也可能不切实际)。
相反,我认为最好使用校验和方法并比较两个表的校验和。
我开发了一个 Python 脚本,可以让您轻松进行此类比较,并在网络浏览器中查看差异:
https://github.com/bolcom/hive_compared_bq
希望对您有所帮助!
一个简单的解决方案是进行内部联接。假设我们有两个配置单元 table,即 table1 和 table2。 table 都有相同的列,即 col1、col2 和 col3。行数也应该相同。然后命令如下
**
select count(*) from table1
inner join table2
on table1.col1 = table2.col1
and table1.col2 = table2.col2
and table1.col3 = table2.col3 ;
**
如果输出值与 table1 和 table2 中的行数相同,则所有列都具有相同的值,但是如果输出计数小于某些数据这是不同的。
首先获取表 C1 和 C2 的计数。 C1 和 C2 应该相等。 C1和C2可以通过以下查询得到
select count(*) from table1
如果 C1 和 C2 不相等,则表不相同。
2:查找表 DC1 和 DC2 的非重复计数。 DC1 和 DC2 应该相等。可以使用以下查询找到不同记录的数量:
select count(*) from (select distinct * from table1)
如果 DC1 和 DC2 不相等,则表不相同。
3:现在获取对2张表进行联合得到的记录数。假设为 U。使用以下查询获取 2 个表的联合中的记录数:
SELECT count (*)
FROM
(SELECT *
FROM table1
UNION
SELECT *
FROM table2)
如果2个表的distinct count等于2个表union得到的记录数,就可以说2个表的数据是一样的。即 DC1 = U 和 DC2 = U
嗯,最好的办法是计算每个table的哈希和,然后比较哈希和。 所以无论它们有多少列,无论它们是什么数据类型,只要两者table具有相同的架构,就可以使用以下查询进行比较:
select sum(hash(*)) from t1;
select sum(hash(*)) from t2;
您只需要比较 return 个值。
我使用了 EXCEPT 语句并且有效。
select * from Original_table
EXCEPT
select * from Revised_table
将向我们显示原始 table 中未包含在修订版 table 中的所有行。
如果您的 table 已分区,您将必须提供分区谓词。 仅供参考,如果您使用 Presto 并通过 SQL 实验室进行查询,则不需要提供分区值。