【问题标题】:Joining two Tables in Hive using HiveQL(Hadoop) [duplicate]使用 HiveQL(Hadoop) 在 Hive 中连接两个表 [重复]
【发布时间】:2012-07-05 10:07:33
【问题描述】:

可能重复:
SQL Query JOIN with Table

CREATE EXTERNAL TABLE IF NOT EXISTS TestingTable1   (This is the MAIN table through which comparisons need to be made)
(
BUYER_ID BIGINT,
ITEM_ID BIGINT,
CREATED_TIME STRING
)

这是上面第一个表中的数据

**BUYER_ID**  |  **ITEM_ID**     |      **CREATED_TIME**   
--------------+------------------+-------------------------
 1015826235      220003038067       *2001-11-03 19:40:21*
 1015826235      300003861266        2001-11-08 18:19:59
 1015826235      140002997245        2003-08-22 09:23:17
 1015826235     *210002448035*       2001-11-11 22:21:11

这是 Hive 中的第二张表 - 它还包含有关我们正在购买的物品的信息。

CREATE EXTERNAL TABLE IF NOT EXISTS TestingTable2
(
USER_ID BIGINT,
PURCHASED_ITEM ARRAY<STRUCT<PRODUCT_ID: BIGINT,TIMESTAMPS:STRING>>
)

这是上面第二张表中的数据(TestingTable2)-

**USER_ID**    **PURCHASED_ITEM**
1015826235     [{"product_id":220003038067,"timestamps":"1004941621"},    {"product_id":300003861266,"timestamps":"1005268799"},    {"product_id":140002997245,"timestamps":"1061569397"},{"product_id":200002448035,"timestamps":"1005542471"}]

TestingTable2TestingTable1 进行比较,以实现以下场景。

TestingTable2 中找到与 ITEM_IDCREATED_TIME 不匹配的 PRODUCT_IDTIMESTAMPSTestingTable1 比较后对应于 BUYER_ID(USER_ID) 的 TestingTable1。

因此,如果您查看TestingTable2 数据,则TestingTable1 中的ITEM_ID 210002448035TestingTable2 PRODUCT_ID- 200002448035 数据不匹配,并且与时间戳类似。所以我想使用 HiveQL 查询显示以下结果。

**BUYER_ID**  |  **ITEM_ID**     |      **CREATED_TIME**          |  **PRODUCT_ID**    |     **TIMESTAMPS** 
--------------+------------------+--------------------------------+------------------------+----------------------
1015826235          *210002448035*           2001-11-11 22:21:11            200002448035           1005542471 
1015826235       220003038067           *2001-11-03 19:40:21*           220003038067          1004941621

谁能帮我解决这个问题。由于我是 HiveQL 的新手,所以遇到了很多问题。

更新:-

我已经编写了这个查询,但它没有按照我想要的方式工作。

select * from 
  (select * from 
     (select user_id, prod_and_ts.product_id as product_id, prod_and_ts.timestamps as timestamps 
      from testingtable2 LATERAL VIEW
      explode(purchased_item) exploded_table as prod_and_ts)
      prod_and_ts 
      LEFT OUTER JOIN testingtable1 
  ON ( prod_and_ts.user_id = testingtable1.buyer_id AND testingtable1.item_id =    prod_and_ts.product_id
     AND prod_and_ts.timestamps = UNIX_TIMESTAMP (testingtable1.created_time)
  )
  where testingtable1.buyer_id IS NULL) 
  set_a LEFT OUTER JOIN testingtable1 
  ON (set_a.user_id = testingtable1.buyer_id AND  
  ( set_a.product_id = testingtable1.item_id OR set_a.timestamps = UNIX_TIMESTAMP(testingtable1.created_time) )
 );

更多更新

根据user1166147 cmets。我根据他的查询写了我的查询。 在 Hive 中,我猜 INNER JOIN 是由 JOIN 编写的。

这是我的以下查询。

select * from (select t2.buyer_id, t2.item_id, t2.created_time as created_time, subq.user_id, subq.product_id, subq.timestamps as timestamps 
from
(select user_id, prod_and_ts.product_id as product_id, prod_and_ts.timestamps as timestamps from testingtable2 lateral view explode(purchased_item) exploded_table as prod_and_ts) subq JOIN testingtable1 t2 on t2.buyer_id = subq.user_id 
AND subq.timestamps = unix_timestamp(t2.created_time)
WHERE (subq.product_id <> t2.item_id)
union all
select t2.buyer_id, t2.item_id as item_id, t2.created_time, subq.user_id, subq.product_id as product_id, subq.timestamps
from 
(select user_id, prod_and_ts.product_id as product_id, prod_and_ts.timestamps as timestamps from testingtable2 lateral view explode(purchased_item) exploded_table as prod_and_ts) subq JOIN testingtable1 t2 on t2.buyer_id = subq.user_id 
    and subq.product_id = t2.item_id 
    WHERE (subq.timestamps <> unix_timestamp(t2.created_time))) unionall;

运行上述查询后,我得到的结果为零。

最后一次更新:-

我的错,我的表格中没有准确的数据,所以这就是我没有得到结果的原因。是的,它正在执行上述实际查询。

【问题讨论】:

  • @biziclop,感谢编辑,有什么建议可以达到我想要的结果吗?
  • 对不起,我不是 Hive 专家,也许是其他人 :)
  • 引用查询的“它不起作用”是什么意思?你得到了什么结果?
  • 首先,我在使用 HiveQL 时遇到 OR is not allowed in JOIN query 错误。如果我将其更改为 AND 之类的其他名称,我将不会得到任何结果。

标签: sql hadoop mapreduce hive hiveql


【解决方案1】:

编辑 - 第 1 部分 好的 - 出于某种原因,我要解释一下自己 - 所以首先我偶然发现了这个问题,因为 SQL 标签,看到了 Hive,开始不看,只是跳过它。但后来我注意到已经过去一天了,你还没有得到任何答案。我看了看 - 我在发布的原始查询中看到了一个 SQL 逻辑更正,我知道这将是必要的并且会有所帮助,所以我发布只是因为没有人回答。我将尝试解决最后一个问题——但在那之后我会保留我的建议,因为我可能会给出不好的建议。祝你好运!我试过了!你现在似乎得到了答案,所以......

在 TSQL 中,我可以通过以下单个查询来解决整个问题

SELECT * 
FROM SO_Table1HIVE A
FULL OUTER JOIN SO_Table2HIVE B ON A.BUYER_ID = B.[USER_ID] AND (B.t1time = A.Created_TIME OR B.PRODUCTID = A.ITEM_ID)

它将返回所有内容,仅包括您的匹配购买者 ID/用户 ID。它不会匹配在另一个表中的 time 或 product 中没有匹配的 buyer_id/user_id 行,但它会在另一个表的字段中将其作为单独的行返回,并带有 NULLS。我不会以任何方式匹配这些 - 没有提供准确的信息来做到这一点,如下所述。

结束编辑第 1 部分

如果你不能在 Hive 中用ORFULL OUTER JOIN,满足原始条件的最简单方法是UNION ALL 2 INNER JOINs。在其中一个查询中,除了加入匹配的 user_id 之外,加入 PRODUCT_ID 并在您的WHERE 中查找与 CREATED_TIME 不匹配的 TIMESTAMPS。在第二个查询中,除了加入匹配的 user_ids 之外,加入时间 AND 在您的 WHERE 中查找不匹配的产品。

编辑第 2 部分 - 评论问题附加标准的更新

如果我理解最后一个条件,那就是任一表中的任何记录都具有匹配的 user_id = Buyer_id,但没有其他匹配项。 FULL OUTER JOINOR 条件将返回它们,但提供的信息不足以将记录相互关联。我们可以很容易地识别它们,但无法将它们相互联系起来。如果您这样做并且在任一或两个表中都有多个不匹配的记录,则每个表将有多个条目。

我写的任何查询都试图在没有更多信息(并且可能有)的情况下将它们联系起来,这都是猜测和不准确的。

例如,在第一个表中,如果有这 2 条(假样本)记录,第二个中除了 user_id 之外没有任何匹配项:

1015826235  420003038067    2011-11-03 19:40:21.000
1015826235  720003038067    2004-11-03 19:40:21.000

表 2 中的 AND - 这些不匹配:

1015826235  {"product_id":520003038067,"timestamps":"10...
1015826235  {"product_id":620003038067,"timestamps":"10...

您可以识别它们,但如果您在没有更多条件的情况下匹配它们,您会得到 4 而不是 2:

1015826235  420003038067    2011-11-03 19:40:21.000 1015826235 520003038067
1015826235  420003038067    2011-11-03 19:40:21.000 1015826235 620003038067
1015826235  720003038067    2004-11-03 19:40:21.000 1015826235 520003038067
1015826235  720003038067    2004-11-03 19:40:21.000 1015826235 620003038067

我的建议是简单地识别它们并显示它们,如下所示。

BUYER_ID        ITEM_ID      CREATED_TIME           USER_ID PRODUCTID   timestamps  
----------------------------------------------------------------------
NULL            NULL         NULL                   1015826235  520003038067    2009-11-11 22:21:11.000
NULL            NULL         NULL                   1015826235  620003038067    2008-11-11 22:21:11.000
1015826235      420003038067 2011-11-03 19:40:21.000    NULL    NULL    NULL    
1015826235      720003038067 2004-11-03 19:40:21.000    NULL    NULL    NULL    

结束编辑第 2 部分 - 更新评论问题附加标准 - 第 1 部分

我正在使用 TSQL,所以我无法用你的语法为你测试一个精确的查询,但连接的概念是相同的,这将返回你想要的。我确实接受了您的查询并尝试了您的语法,并根据需要进行了修改。我在 TSQL 中测试过。您也许可以使用 HiveQL 中的功能并对其进行改进。还有其他方法可以做到这一点 - 但这是最​​直接的,这将转化为 HiveQL。

已删除,您得到了这部分,稍后会包含它

(再次根据需要修改语法)**

SELECT *
FROM (
    SELECT BUYER_ID,ITEM_ID,CREATED_TIME,PRODUCT_ID,TIMESTAMPS 
    FROM testingtable2 LATERAL VIEW
        explode(purchased_item) exploded_table as prod_and_ts)
        prod_and_ts 
    INNER JOIN table2 A  ON A.BUYER_ID = prod_and_ts.[USER_ID] AND prod_and_ts.timestamps = UNIX_TIMESTAMP (table2.created_time) 
    WHERE prod_and_ts.product_id <> A.ITEM_ID
    UNION ALL
    SELECT BUYER_ID,ITEM_ID,CREATED_TIME,PRODUCT_ID,TIMESTAMPS 
    FROM testingtable2 LATERAL VIEW
            explode(purchased_item) exploded_table as prod_and_ts)
            prod_and_ts 
    INNER JOIN table2 A  ON A.BUYER_ID = prod_and_ts.[USER_ID] AND prod_and_ts.product_id = A.ITEM_ID
    WHERE  prod_and_ts.timestamps <> UNIX_TIMESTAMP (table2.created_time) 
) X

这是我的经过测试的 TSQL 版本,其中包含我的表名供参考:

SELECT * 
FROM(
    SELECT *
    FROM SO_Table1HIVE A
    INNER JOIN SO_Table2HIVE B ON A.BUYER_ID = B.[USER_ID] AND B.t1time = A.Created_TIME 
    WHERE B.PRODUCTID <> A.ITEM_ID
    UNION ALL
    SELECT * 
    FROM SO_Table1HIVE A
    INNER JOIN SO_Table2HIVE B ON A.BUYER_ID = B.[USER_ID] AND B.PRODUCTID = A.ITEM_ID  
    WHERE B.t1time <> A.Created_TIME  
 ) X

*编辑第 3 部分 - 更新评论问题附加标准 - 第 2 部分

在 TSQL 中,整个查询(无联合)可以使用 FULL OUTER JOINOR 连接条件运行

SELECT * 
FROM SO_Table1HIVE A
FULL OUTER JOIN SO_Table2HIVE B ON A.BUYER_ID = B.[USER_ID] AND (B.t1time = A.Created_TIME OR B.PRODUCTID = A.ITEM_ID)

如果您不能简单地执行上述操作,对于新条件的 SQL 逻辑 - 要从两个表中获取不匹配的那些并在另一个表中将它们显示为 NULL,请使用 RIGHT JOIN 和 @ 987654342@。 RIGHT JOIN 将抓取第一个表中的任何内容,匹配第二个以及第二个中的所有内容,而 LEFT 则相反。将新查询添加到您的 UNION

TSQL 示例 - 针对 HIVE 进行修改

SELECT * 
FROM SO_Table1HIVE A
RIGHT JOIN SO_Table2HIVE B ON A.BUYER_ID = B.[USER_ID] AND (B.t1time = A.Created_TIME    OR B.PRODUCTID = A.ITEM_ID)
WHERE A.BUYER_ID IS NULL 
UNION ALL
SELECT * 
FROM SO_Table1HIVE A
LEFT JOIN SO_Table2HIVE B ON A.BUYER_ID = B.[USER_ID] AND (B.t1time = A.Created_TIME OR    B.PRODUCTID = A.ITEM_ID)
WHERE B.[USER_ID] IS NULL

或者,如果你想获取它们并将它们作为重复项添加到UNION

TSQL

SELECT * 
FROM SO_Table1HIVE A
JOIN SO_Table2HIVE B ON A.BUYER_ID = B.[USER_ID] 
WHERE B.t1time NOT IN(SELECT Created_TIME FROM SO_Table1HIVE)
AND A.Created_TIME  NOT IN(SELECT t1time FROM SO_Table2HIVE) 
AND B.PRODUCTID NOT IN(SELECT ITEM_ID FROM SO_Table1HIVE)
AND A.ITEM_ID NOT IN(SELECT PRODUCTID FROM SO_Table2HIVE) 

再次祝你好运!

【讨论】:

  • 感谢您的详细回答。非常感谢。但是HiveQL 的问题是它不支持INNER JOIN 和不支持&lt;&gt;,所以这就是我出现整个问题的原因。我会试试这个,然后它会告诉我当前不支持 INNER JOIN 的错误。 https://karmasphere.com/hive-queries-on-table-data.
  • 不使用INNER JOIN&lt;&gt;有什么办法吗?
  • 我认为 INNER JOIN 有效,我尝试了简单的查询我得到了一些结果。但是当我按照您建议的方式编写查询时,我遇到了一些错误。我已经根据你的回答编辑了我的问题,你能指出我做错了什么吗,我想我猜有一些语法错误。我已经更新了我的问题,你能看看我做错了什么吗?
  • 好的。还有一个更新,Hive 中的INNER JOIN 是由JOIN 编写的。我用答案更新了我的问题。在运行我的查询后,我没有得到任何结果返回零结果。而且我已经用我正在使用的实际表名更新了我的问题。
  • 我刚刚签到,看起来你接受了这个,修改了 hive 语法,并在这个评论之后让它工作?真的吗? (如果是这样,那就太好了!)
【解决方案2】:

您可能需要使用Hive transform functionality 并有一个自定义reducer 来匹配两个表中的记录:t1 和t2,其中t1 只是TestingTable1 而t2 是

   SELECT
      user_id,
      prod_and_ts.product_id as product_id,
      prod_and_ts.timestamps as timestamps
   FROM 
      TestingTable2 
      LATERAL VIEW explode(purchased_item) exploded_table as prod_and_ts

as explained by me in another question of yours.

FROM (
   FROM (
      SELECT
         buyer_id,
         item_id,
         created_time,
         id 
      FROM (
         SELECT
            buyer_id,
            item_id,
            created_time,
            't1' as id
         FROM
            TestingTable1 t1
         UNION ALL
         SELECT
            user_id as buyer_id,
            prod_and_ts.product_id as item_id,
            prod_and_ts.timestamps as created_time,
            't2' as id
         FROM 
            TestingTable2
            LATERAL VIEW explode(purchased_item) exploded_table as prod_and_ts
         )t
      )x
      MAP
         buyer_id,
         item_id,
         created_time,
         id
      USING '/bin/cat'
      AS
         buyer_id,
         item_id,
         create_time,
         id
      CLUSTER BY
         buyer_id
      ) map_output
   REDUCE 
      buyer_id,
      item_id,
      create_time,
      id
   USING 'my_custom_reducer'
   AS
      buyer_id,
      item_id,
      create_time,
      product_id,
      timestamps;

上述查询有 2 个不同的部分。第一部分是“MAP”,另一部分是“REDUCE”。在这两个部分之间是一个称为 shuffle 的阶段(由 CLUSTER BY buyer_id 表示),它会自动处理我的 Hive。查询的 Map 部分从表中读取并传递一个标识符(称为 id,表示记录来自哪些表)。 Shuffle 阶段根据 buyer_id 对所有记录进行分组。 Reduce 阶段将接收给定 buyer_id 的所有记录,并仅发出满足匹配条件的记录。您必须根据匹配标准自己编写减速器。您可以用您选择的任何语言编写它。保证所有具有相同buyer_id 的记录都会进入同一个reducer 脚本。

可能有更简单的方法,但这是我现在能想到的方法。祝你好运!为了进一步了解我为什么选择这种方法,see my recent answer here

【讨论】:

  • 感谢马克的出色回答。但是,如果我按原样运行上述查询,则会出现错误。错误是-FAILED: Parse Error: line 18:18 mismatched input 't2' expecting EOF。有什么建议为什么会这样?
  • 有一个小错误。你能再试一次吗?
  • 我会试试的。感谢您的所有帮助。
  • 感谢马克的出色回答。我还有一个与 Hive 相关的查询,我尝试过但无法得到我需要的答案,因为 HiveQL 语法与 SQL 完全不同,所以有很多问题。http://stackoverflow.com/questions/11405446/find-10-latest-record-for-each-buye‌​r-id-basis-on-time。对我会有很大的帮助。谢谢。
  • 我又发布了一个问题,因为它是更多与性能测量相关的理论问题。http://stackoverflow.com/questions/11404163/custom-mapper-and-reduc‌​er-vs-hiveql。如果我在 SO 上给您带来如此多的困扰,我深表歉意,这里没有那么多 BIG DATA 专家。所以这就是我ping你的原因。非常感谢您的所有帮助...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-10
相关资源
最近更新 更多