HIVE:如何仅从两个表中的两列中选择第三个表中不存在的不同值?

Posted

技术标签:

【中文标题】HIVE:如何仅从两个表中的两列中选择第三个表中不存在的不同值?【英文标题】:HIVE: How to only select distinct values from two columns in two tables that does not exist in a third table? 【发布时间】:2019-10-04 11:16:32 【问题描述】:

我有三张桌子。

t1
Name | Version | ...
A        1 
A        2
B        1
B        3

t2
Name  | Version | ...
 A        1
 A        3
 B        2
 B        3

 t3 
 Name  | Version | ...
  A         1
  A         2

我想从表 1 和表 2 中选择表 3 中不存在的不同名称和版本值。

我当前的 SELECT 查询通过

从表 1 和表 2 中选择不同的值
SELECT c.name,c.version FROM 
   (SELECT name,version from t1 
    UNION   
    SELECT name,version from t2
    ) c

返回

 result
 Name  | Version
  A        1
  A        2 
  A        3
  B        1
  B        2
  B        3

我想要什么

wanted result
Name | Version
  A      3
  B      1
  B      2
  B      3

如何正确修改 HQL 查询以获得此结果?感谢您提供的任何帮助。

【问题讨论】:

【参考方案1】:

将 LEFT JOIN 与 t3 表一起使用 + 仅过滤未连接的行:

SELECT c.name,c.version 
  FROM 
   (SELECT name,version from t1 
    UNION   
    SELECT name,version from t2
    ) c
  LEFT JOIN t3 on c.name=t3.name and c.version=t3.version
WHERE t3.name is NULL --do not exist in t3 table
;

另一种可能的方法是使用 NOT EXISTS:

SELECT c.name,c.version 
  FROM 
   (SELECT name,version from t1 
    UNION   
    SELECT name,version from t2
    ) c
WHERE NOT EXISTS (SELECT 1 FROM t3 WHERE c.name=t3.name and c.version=t3.version)
;

【讨论】:

我读了一些 HIVE 语法,这和使用 LEFT SEMI JOIN 一样吗? @kspr Hive 仅在您不需要引用左表列时才支持 LEFT SEMI JOIN,它可以有效地作为 IN/EXISTS 工作。但是在您的情况下,您不需要存在,这就是使用 LEFT JOIN + 过滤器的原因。 LEFT SEMI JOIN 与您的要求相反 @kspr 使用 NOT EXISTS 添加了一个选项【参考方案2】:

你可以在连接条件中使用

 SELECT c.name,c.version 
  FROM 
   (SELECT name,version from t1 
    UNION   
    SELECT name,version from t2
    ) c
  INNER JOIN t3 on c.name<>t3.name and c.version<>t3.version

【讨论】:

以上是关于HIVE:如何仅从两个表中的两列中选择第三个表中不存在的不同值?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过比较两个表中的两列来更新表中的列

从表中的两列中选择相同的数据,并使用一条sql语句显示所有数据

使用 Laravel 中的验证器检查两个表中两列的唯一性

两个表,一个表中的两列关联另一个表的id,如何将这个表中的两列显示为另一个表id对应的内容

如何将两个单独表中的两列拆分为视图中的多行?

如何将前 2 个 hive 表中的数据加载到下面的第三个表中?