【问题标题】:Are Hive's implicit joins always inner joins?Hive 的隐式连接总是内部连接吗?
【发布时间】:2018-04-01 00:53:27
【问题描述】:

Hive 的 join documentation 鼓励使用隐式连接,即

SELECT * 
FROM table1 t1, table2 t2, table3 t3 
WHERE t1.id = t2.id AND t2.id = t3.id AND t1.zipcode = '02535';

这是否等同于

SELECT t1.*, t2.*, t3.*
FROM table1 t1
INNER JOIN table2 t2 ON
  t1.id = t2.id 
INNER JOIN table3 t3 ON
  t2.id = t3.id
WHERE t1.zipcode = '02535'

,还是上面会返回额外的记录?

【问题讨论】:

    标签: hadoop join hive hiveql


    【解决方案1】:

    并非总是如此。您的查询是等效的。但如果没有WHERE t1.id = t2.id AND t2.id = t3.id,它将是CROSS JOIN

    更新:

    这是一个有趣的问题,我决定添加一些演示。让我们创建两个表:

    A(c1 int, c2 string)B(c1 int, c2 string)

    加载数据:

    insert into table A
     select 1, 'row one' union all
     select 2, 'row two';
    
    insert into table B
     select 1, 'row one' union all
     select 3, 'row three';
    

    检查数据:

    hive> select * from A;
    OK
    1       row one
    2       row two
    Time taken: 1.29 seconds, Fetched: 2 row(s)
    hive> select * from B;
    OK
    1       row one
    3       row three
    Time taken: 0.091 seconds, Fetched: 2 row(s)
    

    检查交叉连接(隐式连接没有where 转换为交叉):

    hive> select a.c1, a.c2, b.c1, b.c2 from a,b;
    Warning: Map Join MAPJOIN[14][bigTable=a] in task 'Stage-3:MAPRED' is a cross product
    Warning: Map Join MAPJOIN[22][bigTable=b] in task 'Stage-4:MAPRED' is a cross product
    Warning: Shuffle Join JOIN[4][tables = [a, b]] in Stage 'Stage-1:MAPRED' is a cross product
    
    OK
    1       row one 1       row one
    2       row two 1       row one
    1       row one 3       row three
    2       row two 3       row three
    Time taken: 54.804 seconds, Fetched: 4 row(s)
    

    检查内连接(与where 的隐式连接用作INNER):

    hive> select a.c1, a.c2, b.c1, b.c2 from a,b where a.c1=b.c1;
    OK
    1       row one 1       row one
    Time taken: 38.413 seconds, Fetched: 1 row(s)
    

    尝试通过将OR b.c1 is null 添加到 where 来执行左连接:

    hive> select a.c1, a.c2, b.c1, b.c2 from a,b where (a.c1=b.c1) OR (b.c1 is null);
    OK
    1       row one 1       row one
    Time taken: 57.317 seconds, Fetched: 1 row(s)
    

    如您所见,我们再次获得了内部连接。 or b.c1 is null 被忽略

    现在left join 没有whereON 子句(转换为CROSS):

     select a.c1, a.c2, b.c1, b.c2 from a left join b;
    OK
    1       row one 1       row one
    1       row one 3       row three
    2       row two 1       row one
    2       row two 3       row three
    Time taken: 37.104 seconds, Fetched: 4 row(s)
    

    如你所见,我们又发脾气了。

    尝试使用 where 子句和不使用 ON 的左连接(作为 INNER):

    select a.c1, a.c2, b.c1, b.c2 from a left join b where a.c1=b.c1;
    OK
    1       row one 1       row one
    Time taken: 40.617 seconds, Fetched: 1 row(s)
    

    我们获得了 INNER 加入

    尝试使用where 子句和不使用ON+ 的左连接尝试允许空值:

     select a.c1, a.c2, b.c1, b.c2 from a left join b where a.c1=b.c1 or b.c1 is null;
    OK
    1       row one 1       row one
    Time taken: 53.873 seconds, Fetched: 1 row(s)
    

    再次获得内心。或b.c1 is null 被忽略。

    on 子句左连接:

    hive> select a.c1, a.c2, b.c1, b.c2 from a left join b on a.c1=b.c1;
    OK
    1       row one 1       row one
    2       row two NULL    NULL
    Time taken: 48.626 seconds, Fetched: 2 row(s)
    

    是的,确实是左连接。

    左加入 on + where(得到 INNER):

    hive> select a.c1, a.c2, b.c1, b.c2 from a left join b on a.c1=b.c1 where a.c1=b.c1;
    OK
    1       row one 1       row one
    Time taken: 49.54 seconds, Fetched: 1 row(s)
    

    我们得到了 INNER,因为 WHERE 不允许 NULL。

    左加入 where + 允许空值:

    hive> select a.c1, a.c2, b.c1, b.c2 from a left join b on a.c1=b.c1 where a.c1=b.c1 or b.c1 is null;
    OK
    1       row one 1       row one
    2       row two NULL    NULL
    Time taken: 55.951 seconds, Fetched: 2 row(s)
    

    是的,它是左连接。

    结论:

    1. 如果没有 WHERE,则隐式连接可用作 INNNER(带有 where)或 CROSS 条款。
    2. 如果没有 ON 和没有 WHERE,左连接可以作为 CROSS 工作,如果 WHERE 子句不允许空值,也可以作为 INNER 为权 表。
    3. 最好使用 ANSI 语法,因为它是不言自明的,并且很容易理解您期望它的工作方式。作为 INNER 或 CROSS 工作的隐式连接或左连接很难理解并且很容易出错。

    【讨论】:

    • 当我遇到更复杂的查询时,我终于回到了这个话题。非常酷的行为文档。
    • 这些复杂的demo很清楚知道怎么写inner join和left join。非常感谢!
    猜你喜欢
    • 2013-12-13
    • 2020-01-26
    • 1970-01-01
    • 2019-04-03
    • 2019-11-02
    • 1970-01-01
    • 1970-01-01
    • 2021-06-24
    • 1970-01-01
    相关资源
    最近更新 更多