5

重複の可能性:
テーブルを使用したSQLクエリJOIN

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の2番目のテーブルです-これには、購入しているアイテムに関する情報も含まれています。

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

そしてこれは上の2番目の表のデータです(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"}]

以下のシナリオが満たされるようにと比較TestingTable2してください。TestingTable1

から比較した後、 TestingTable1に対応するANDと一致しないPRODUCT_IDANDTIMESTAMPSを検索します。TestingTable2ITEM_IDCREATED_TIMEBUYER_ID(USER_ID)TestingTable1

したがって、データを見るとTestingTable2、this(last)ITEM_ID 210002448035fromTestingTable1はデータと一致しておらずTestingTable2 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) )
 );

もう1つの更新

user1166147コメントによると。私は彼の質問に従って私の質問を書きました。ハイブでは、私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;

そして、上記のクエリを実行した後、ゼロの結果が返されます。

1つの最終更新:-

残念ながら、テーブルに正確なデータがなかったため、結果が返されませんでした。はい、実際の上記のクエリを実行しています。

4

2 に答える 2

6

編集-パート1 わかりました-何らかの理由で私は自分自身を説明するつもりです-それで私はSQLタグのためにこの質問に出くわし、Hiveを見て、見ずにそれをスキップし始めました。しかし、それから私はそれが1日以上過ぎていて、あなたが答えを得ていなかったことに気づきました。調べた-投稿された元のクエリでSQLロジックの修正が必要であり、役立つことがわかっていたので、誰も回答しなかったという理由だけで投稿しました。私はこの最後の質問に対処しようとしますが、その後、悪いアドバイスをしている可能性があるため、自分自身にアドバイスを続けています。幸運を!私は試した!そして、あなたは今答えを得ているようです、それで...

TSQLでは、次の1つのクエリでこの問題全体を解決できます

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行とは一致しませんが、他のテーブルのフィールドにNULLが含まれる別の行として返されます。私はこれらとはまったく一致しません-以下で説明するように、それを行うための正確な情報は提供されていません。

編集パート1を終了

FULL OUTER JOINHiveで処理できない場合OR、元の基準を満たす最も簡単な方法はUNION ALL2INNER JOIN秒です。クエリの1つで、一致するuser_idに参加することに加えて、PRODUCT_IDに参加し、WHERECREATED_TIMEと一致しないTIMESTAMPSを探します。2番目のクエリでは、一致するuser_idsに参加することに加えて、時間に参加し、一致WHEREしない製品を探します。

パート2の編集-コメント質問の追加基準の更新

最後の基準を理解すると、user_id = Buyer_idが一致するいずれかのテーブルのレコードですが、他に一致するものはありません。FULL OUTER JOINwith条件はそれら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...

それらを識別することはできますが、それ以上の基準なしでそれらに一致すると、2ではなく4が得られます。

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 JOINの条件を使用してクエリ全体(ユニオンなし)を実行できますOR

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 JOINLEFT JOINます。 RIGHT JOIN最初のテーブルのすべてを取得し、2番目のテーブルと一致し、2番目のテーブルのすべてを取得し、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) 

繰り返しますが、頑張ってください!

于 2012-07-09T16:09:19.543 に答える
1

おそらく、Hive変換機能を使用し、2つのテーブル(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

あなたの別の質問で私が説明したように

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」で、もう1つは「REDUCE」です。これらの2つの部分の間に、シャッフル(で表される)と呼ばれるフェーズがあり、CLUSTER BY buyer_idこれが自動的にハイブの処理を行います。クエリのマップ部分はテーブルから読み取り、識別子(レコードがどのテーブルからのものであるかを表すidと呼ばれる)も渡します。シャッフルフェーズでは、buyer_idごとにすべてのレコードがグループ化されます。削減フェーズでは、特定のbuyer_idのすべてのレコードが取り込まれます一致基準を満たすレコードのみを出力します。一致基準に基づいて、自分でレデューサーを作成する必要があります。あなたはそれをあなたの選んだ言語で書くことができます。同じbuyer_idを持つすべてのレコードが、同じレデューサースクリプトに送られることが保証されています。

もっと簡単な方法があるかもしれませんが、これは私が今考えることができる方法です。幸運を!私がこの方法を選んだ理由をさらに理解するには、ここで私の最近の回答を参照してください

于 2012-07-09T23:09:31.410 に答える