Hive - 具有左外连接的 OR 条件

Posted

技术标签:

【中文标题】Hive - 具有左外连接的 OR 条件【英文标题】:Hive - OR condition with left outer join 【发布时间】:2018-01-16 10:48:23 【问题描述】:

我已经参考了所有关于 SO 的类似案例的查询。尽管错误可能很常见,但我正在寻找针对特定情况的解决方案。请不要将问题标记为重复,除非您得到完全相同的方案和可接受的解决方案。


我有两张桌子

Main table:

c1  c2  c3  c4  c5
1   2   3   4   A

Other table

c1  c2  c3  c4  c5
1   8   5   6   B
8   2   8   9   C
8   7   3   9   C
8   7   9   4   C
5   6   7   8   D

现在,从另一个表中,我应该只能在所有列中选择唯一记录。例如仅最后一行 (5,6,7,8, D)。

其他表的第 1 行被拒绝,因为 c1 值 (1) 与主表中的 c1 值 (1) 相同,第 2 行被拒绝,因为其他表和主表的 c2 值匹配,同样...

简而言之,在查询输出的主表中,其他表中的列都不应具有相同的值(在相应列中)。


我尝试在下面创建查询

select t1.* from otherTable t1
LEFT OUTER JOIN mainTable t2
ON ( t1.c1 = t2.c1 OR t1.c2 = t2.c2 OR t1.c3 = t2.c3 OR t1.c4 = t2.c4 )
Where t2.c5 is null;

但是,hive 会抛出异常

或目前在 JOIN 中不支持

我了解 hive 的限制,并且我多次使用 UNION (ALL | DISTINCT) 和内部连接来克服这个限制;但不能对此使用相同的策略。

请帮忙。

EDIT 1 : 我有 hive 版本限制 - 只能使用 1.2.0 版

【问题讨论】:

“只选择所有列中的唯一记录”是语言不清楚的片段。 “[the] 其他表中的任何列都不应在 [the] 主表中具有相同的值(在 [the] 对应列中)”很清楚。 (因此它不是“简而言之”,意思是不清楚和简洁,但希望有助于掌握或记住 其他一些描述 清晰。请花时间写下什么你的意思是让不知道你意思的人知道。像我们一样。当你说清楚时,你不必(模糊地)再说一遍。 【参考方案1】:

您可以进行笛卡尔积连接(无条件的内连接):

select t1.* from otherTable t1
,mainTable t2
WHERE  t1.c1 != t2.c1 AND t1.c2 != t2.c2 
       AND t1.c3 != t2.c3 AND t1.c4 != t2.c4 AND t1.c5 !=  t2.c5;

假设您在mainTable 中有一行,此查询应该与使用OUTER JOIN 的查询一样有效

另一种选择是将您提出的查询分成 5 个不同的LEFT OUTER JOIN 子查询:

select t1.* from (
  select t1.* from (
    select t1.* from (
      select t1.* from (
        select t1.* from otherTable t1
        LEFT OUTER JOIN (select distinct c1 from mainTable) t2
        ON ( t1.c1 = t2.c1) Where t2.c1 is null ) t1
      LEFT OUTER JOIN (select distinct c2 from mainTable) t2
      ON ( t1.c2 = t2.c2) Where t2.c2 is null ) t1
    LEFT OUTER JOIN (select distinct c3 from mainTable) t2
    ON ( t1.c3 = t2.c3) Where t2.c3 is null ) t1
  LEFT OUTER JOIN (select distinct c4 from mainTable) t2
  ON ( t1.c4 = t2.c4) Where t2.c4 is null ) t1
LEFT OUTER JOIN (select distinct c5 from mainTable) t2
ON ( t1.c5 = t2.c5) Where t2.c5 is null
;

在这里,对于每一列,我首先从mainTable 中获取不同的列,并将其与otherTable 的剩余部分连接起来。缺点是我通过了 5 次超过 mainTable - 每列一次。如果主表中的值是唯一的,您可以从子查询中删除distinct

【讨论】:

由于 Hive 是一个仓库,因此假设它会有 TB 的数据,并且没有条件的内部连接不是一个可行的选择。如果这是唯一的解决方案,那么我最好编写一个 Map-Reduce 程序来处理数据并在输出时重新创建一个配置单元表。 @gyan 内部/交叉版本是您想要的明显表达。内部连接和交叉连接意味着相同的事情。甚至 Hive 也知道这一点。你为什么害怕内部/交叉连接?外部联接只是内部/交叉联接,它还添加了由空值扩展的不匹配的左表行。您已经期望 Hive 知道如何使用连接优化位置。 我不担心内部连接 ​​[with a join condition],它根本无法解决这种特定情况。如果我没有得到它,请帮助我构建查询。交叉连接是不可行的,因为主表有 9.7 亿条(~5 TB)记录,而另一个表有 15 亿条记录(~7 TB),我们有一个时间窗口来处理它们。如果 hive 1.2.0 没有最优解,Hive UDF 或 MR 仍然是唯一的选择。 @gyan 添加了一个可能的解决方案,它可能在您的时间范围内有效。

以上是关于Hive - 具有左外连接的 OR 条件的主要内容,如果未能解决你的问题,请参考以下文章

左外连接导轨在 where 条件下具有急切加载

Hive SQL 多个左外连接查询在其结果中缺少记录

在 hive 中使用 Null 检查的左外连接查询不起作用

Hive sql中的 各种join(内连接左外连接右外连接满外连接)

Hive sql中的 各种join(内连接左外连接右外连接满外连接)

Hive sql中的 各种join(内连接左外连接右外连接满外连接)