使用HiveQL(Hadoop)在Hive中加入两个表

时间:2012-07-05 01:39:12

标签: sql hadoop mapreduce hive hiveql

  

可能重复:
  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进行比较,以便完成以下方案。

PRODUCT_ID中找出TIMESTAMPSTestingTable2与{1}}和ITEM_ID不匹配来自TestingTable1与CREATED_TIME之后的比较BUYER_ID(USER_ID)

因此,如果您查看TestingTable1来自TestingTable2的{​​{1}}数据ITEM_ID 210002448035TestingTable1 TestingTable2数据不匹配,情况与时间戳类似。所以我想使用HiveQL查询显示以下结果。

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

再续订

根据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仅由INNER JOIN编写。

这是我的以下查询。

JOIN

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

最后一次更新: -

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

2 个答案:

答案 0 :(得分:5)

编辑 - 第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)

它会返回所有内容,包括仅匹配的buyer_id / user_id。它不会匹配在另一个表中的时间或产品中没有匹配的buyer_id / user_id行,但它将在另一个表的字段中将其作为单独的行返回NULLS。我不会以任何方式匹配 - 没有提供准确的信息,如下所述。

结束编辑第1部分

如果您无法在Hive中使用FULL OUTER JOIN OR,则满足原始条件的最简单方法是UNION ALL 2 INNER JOIN s。在其中一个查询中,除了加入匹配的user_ids之外,还可以加入PRODUCT_ID和WHERE查找与CREATED_TIME不匹配的TIMESTAMPS。在第二个查询中,除了加入匹配的user_ids之外,还可以在WHERE中加入时间并查找不匹配的产品。

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

如果我理解了最后一个条件,那么任何一个表中的任何记录都有匹配的user_id = buyer_id,但没有其他匹配。具有FULL OUTER JOIN条件的OR将返回它们,但没有足够的提供信息来将记录相互关联。我们可以轻松识别它们,但无法将它们相互联系起来。如果您这样做并且在两个表中都有多个记录而没有匹配,则每个记录将有多个条目。

我写的任何查询试图在没有更多信息(可能还有)的情况下绑定它们将是猜测和不准确。

例如,在第一个表中,如果除了user_id之外,第二个表中没有匹配的2个(样本伪造)记录:

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

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

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部分 - 更新评论问题附加标准-PART 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使用{{1 }和RIGHT JOINLEFT JOIN会抓住第一个表中与第二个匹配的内容和第二个中的所有内容,而RIGHT JOIN则相反。将新查询添加到LEFT

TSQL示例 - 改善艾滋病病毒

UNION

或者,如果你想抓住它们并将它们作为重复项匹配,请添加到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

TSQL

UNION

再次,祝你好运!

答案 1 :(得分:1)

您可能需要使用Hive transform functionality并拥有一个自定义缩减器来执行两个表中记录之间的匹配: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