配置单元:left join vs join使用on子句中的filter给出不同的结果

ioekq8ef  于 2021-06-28  发布在  Hive
关注(0)|答案(3)|浏览(271)

假设有两张table:

table1.c1   table1.c2
1   1           A
2   1           B
3   1           C
4   2           A
5   2           B

以及

table2.c1   table2.c2
1   2           A
2   2           D
3   3           A
4   3           B

当我这样做时:

select distinct t1.c1, t2.c2
from
schema.table1 t1
join
schema.table2 t2
on (t1.c2 = t2.c2 
    and t1.c1 = t2.c1
    and t1.c1 = 2)

在Hive里,我得到:

t1.c1   t2.c2
1   2   A

这是预期的结果,没问题。但是,当我这么做的时候:

select distinct t1.c1, t2.c2
from
schema.table1 t1
left join
schema.table2 t2
on (t1.c2 = t2.c2 
    and t1.c1 = t2.c1
    and t1.c1 = 2)

我得到:

t1.c1   t2.c2
1   1       NULL
2   2       NULL
3   2       A

所以,filter-in-on子句似乎不像我预期的那样工作。过滤器 t1.c1 = t2.c1 以及 t1.c1 = 2 在左联接中,它在第二个表中找不到键时,没有应用 t2.c2NULL .
我想答案一定在doc中(可能在'joins occure before where子句'部分?),但我仍然不明白其中的区别。
过程是如何给出不同的结果的?

9ceoxa92

9ceoxa921#

就是这样 LEFT (OUTER) JOIN 作品:
您可以在 ON -条款。如果在“right”表中找到匹配的行,它将与“left”表中的行联接。如果没有匹配的行,它仍将返回“left”行以及“right”表中的所有字段设置为null。因此,它永远不会根据 ON -条件。使用配置单元文档的术语:左表是“保留行表”,而右表是“空表”。
这与 INNER JOIN 它只返回在另一个表中有匹配伙伴的行。因此不存在“保留表”,也不需要“空表”

t98cgbkg

t98cgbkg2#

左连接的输出应该与完全连接的输出不同。
left join的输出将包含左表中的所有数据(在两个表中首先写入),如果右表中没有相应的数据,则显示空值。如果从查询中删除distinct并运行它,那么输出应该会消除您对左/右连接工作方式的混淆。
完全联接输出

t1.c1   t1.c2   t2.c2
2       a       a
2       a       d
2       b       a
2       b       d

左连接输出

t1.c1   t1.c2   t2.c2
 1      a       null
 1      b       null
 1      c       null
 2      a       a
 2      a       d
 2      b       a
 2      b       d
gpnt7bae

gpnt7bae3#

显然,在内部连接和左连接中,配置单元对连接条件的处理方式不同。在内部联接中,可以将筛选条件放入on子句中,但在左联接中,需要将主表(本例中为t1)的筛选条件放入单独的where子句中。如果你尝试

`select distinct t1.c1, t2.c2
from
schema.table1 t1
left join
schema.table2 t2
on (t1.c2 = t2.c2 
    and t1.c1 = t2.c1)
where t1.c1 = 2;`

你应该得到预期的结果。

相关问题