我有两个可以通过公共密钥(即交易ID)加入的大型Hive表(数十亿条记录)。 table_a
包含所有交易ID,table_b
在某些时候有交易。
理论上,两个表中都不应有重复的交易ID。在实践中,有一些重复,虽然它们的数量相对较少,但是很多:很多连接都有可能导致问题。我根据这些数据构建模型,作为第一步,可能更容易忽略所有具有重复交易ID的记录。
我写了一个丑陋的Hive查询,虽然它在逻辑上做了它需要做的事情,但它的效率非常低:
SELECT
table_a.someCol,
table_b.anotherCol,
[etc...]
FROM
(SELECT
table_a.*
FROM table_a
INNER JOIN
(SELECT
transaction_id
FROM table_a
GROUP BY transaction_id
HAVING COUNT(*) = 1) unique_transaction_ids
ON table_a.transaction_id = unique_transaction_ids.transaction_id) table_a_unique_transaction_ids_only
LEFT OUTER JOIN
(SELECT
table_b.*
FROM table_b
INNER JOIN
(SELECT
transaction_id
FROM table_b
GROUP BY transaction_id
HAVING COUNT(*) = 1) unique_transaction_ids
ON table_b.transaction_id = unique_transaction_ids.transaction_id) table_b_unique_transaction_ids_only
ON table_a_unique_transaction_ids_only.transaction_id = table_b_unique_transaction_ids_only.transaction_id;
工作原理:
首先,对于两个表,创建一个只出现一次的交易ID列表:
SELECT
transaction_id
FROM table_?
GROUP BY transaction_id
HAVING COUNT(*) = 1
然后通过将唯一事务子查询内部连接到原始表来过滤表。
最后,左外连接已过滤的子查询。
是否有更有效的方式来编写此内容(例如使用ROW_NUMBER() OVER ...
等分析函数)?
答案 0 :(得分:1)
如果您想要table_a
和table_b
,LEFT OUTER JOIN
似乎是不可避免的。可以避免两个自连接。由于您只需要transaction_id
只发生过一次,因此您可以在其余列上使用MAX()
或MIN()
而不会丢失信息(即使它们不是数字列)。像
select transaction_id
, max(col1) col1
, max(col2) col2
.
.
.
, max(coln) coln
from table_a
group by transaction_id
having count(transaction_id) = 1
这是一种通过"拉出列的方式。到下一个"级别"无需group by
他们。如果你有很多专栏,那么编写它可能会很乏味,但通常值得避免两个自连接。