2

以下は、常に日付で降順で並べ替えられた TestingTable1 のデータです。

BUYER_ID  |   ITEM_ID       |  CREATED_TIME
----------+-----------------+----------------------
1345653      110909316904     2012-07-09 21:29:06
1345653      151851771618     2012-07-09 19:57:33
1345653      221065796761     2012-07-09 19:31:48
1345653      400307563710     2012-07-09 18:57:33

そして、これが TestingTable2 の以下のデータであり、日付で常に降順で並べ替えられている場合

USER_ID  |   PRODUCT_ID    |    LAST_TIME
---------+----------------+-----------------------
1345653     110909316904      2012-07-09 22:29:06
1345653     150851771618      2012-07-09 19:57:33    

の各行はTestingTable1と一致する必要TestingTable2があります。一致しない場合、またはデータが TestingTable2 にない場合は、TestingTable1I have this data butに対応するTestingTable2I have this data (これは間違ったデータになります)、何が不一致で、どのデータが欠落しているかを確認できます。

onとを比較する必要がTestingTable2あります。とが一致する場合はとを比較する必要があり、それらのいずれかまたは両方でと比較した後に に不一致がある場合は、結果を表示する必要があります。TestingTable1BUYER_IDUSER_IDBUYER_IDUSER_IDITEM_IDPRODUCT_IDCREATED_TIMELAST_TIMETestingTable2TestingTable1

上記の例を見ると、基本的に3つのシナリオがあります

  1. First- In TestingTable1、最初の行は の最初の行ITEM_IDと一致しPRODUCT_IDますが、両方のテーブルの最初の行ではTestingTable2一致CREATED_TIMEしませんLAST_TIME
  2. Secondly- In TestingTable1、2 番目の行の は の 2 番目の行の とCREATED_TIME一致しますが、両方のテーブルの 2 番目の行のと一致しませんLAST_TIMETestingTable2ITEM_IDPRODUCT_ID
  3. 3 番目にTestingTable1、最後の 2 行 (行) は にはまったくありませんTestingTable2。このシナリオは、私が書いたクエリではカバーされていません。このシナリオもクエリに入れたいです

これらは、alwaysと比較TestingTable2しながらカバーする必要がある 3 つのケースです。TestingTable1またTestingTable1、常に比較を行う必要がある MAIN テーブルであるため、データTestingTable1が常に正確であることを意味します。

したがって、上記の例のいずれにも一致しない場合、またはデータがまったく存在しない場合、次のような結果を表示する必要がありますTestingTable2TestingTable1TestingTable2TestingTable1TestingTable2

BUYER_ID   |   ITEM_ID       |    CREATED_TIME           |      USER_ID   |     PRODUCT_ID     |     LAST_TIME   
-----------+-----------------+---------------------------+----------------+--------------------+-----------------------
1345653      110909316904       2012-07-09 21:29:06            1345653          110909316904      2012-07-09 22:29:06
1345653      151851771618       2012-07-09 19:57:33            1345653          150851771618      2012-07-09 19:57:33
1345653      221065796761       2012-07-09 19:31:48            NULL             NULL              NULL
1345653      400307563710       2012-07-09 18:57:33            NULL             NULL              NULL

以下は、私が上で述べたものだけをカバーする私が書いたクエリであり、two scenarios正常に動作し、出力から最後の2行を残して上記のような出力を取得します。third scenarioただし、上記のような出力が得られるように、この(下の)クエリにも 追加する必要があります。

SELECT *
FROM   (SELECT T2.buyer_id,
               T2.item_id,
               T2.created_time AS created_time,
               subq.user_id,
               subq.product_id,
               subq.LAST_TIME
        FROM   TestingTable2 subq
               JOIN TestingTable1 T2
                 ON T2.buyer_id = subq.user_id
                    AND subq.LAST_TIME = ( 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.LAST_TIME
        FROM   TestingTable2 subq
               JOIN TestingTable1 T2
                 ON T2.buyer_id = subq.user_id
                    AND subq.product_id = T2.item_id
        WHERE  ( subq.LAST_TIME <> ( T2.created_time ) )) finalResult
ORDER  BY finalResult.BUYER_ID;

任意の提案をいただければ幸いです。

PS 過去数日間、JOIN に関連するいくつかの質問をしましたが、それは私の 2 つのシナリオのみをカバーしており、このクエリで必要な 3 番目のシナリオはカバーしていません。

更新:-NOT IN SQL のor構文を 使用できませんNOT EXISTS。Hive を使用しており、Hive はNOT INorNOT EXISTSをサポートしていないため、これに対処するには他の方法が必要です。

クエリを使用する必要があるのは、3 番目のシナリオで機能するようにクエリを変更することだけです。これにより、Hive が SQL 構文をサポートするようになります。

以下は私のSQL Fiddleです。これは、上記の 2 つのシナリオを満たしますが、3 番目のシナリオは満たしません。3番目のシナリオでも機能するようにクエリを変更するのを手伝ってくれる人はいますか?

http://sqlfiddle.com/#!3/102dd/1/0 .

Table1 のデータは Table2 に存在する必要があります。存在しない場合は、Table1 と比較した後にデータ間の不一致を示す必要があります。Table1 のデータが Table2 に存在しない可能性もあります。それも。

フィドルの更新された出力http://sqlfiddle.com/#!3/102dd/3/0

BUYER_ID   |   ITEM_ID       |    CREATED_TIME           |      USER_ID   |     PRODUCT_ID     |     LAST_TIME   
-----------+-----------------+---------------------------+----------------+--------------------+-----------------------
1345653       151851771618      July, 09 2012 19:57:33      1345653            150851771618         July, 09 2012 19:57:33
1345653       221065796761      July, 09 2012 19:31:48      1345653            221165796761         July, 09 2012 19:31:48
1345653       110909316904      July, 09 2012 21:29:06      1345653            110909316904         July, 09 2012 22:29:06
1345653       400307563710      July, 09 2012 18:57:33      NULL               NULL                 NULL
1345653       310411560125      July, 09 2012 16:09:49      NULL               NULL                 NULL

エラーが発生する更新された SQL クエリ

TestingTable1このクエリに置き換えました-

(SELECT BUYER_ID, ITEM_ID, rank(BUYER_ID), CREATED_TIME
FROM (
    SELECT BUYER_ID, ITEM_ID, CREATED_TIME
    FROM testingtable1
    where to_date(from_unixtime(cast(UNIX_TIMESTAMP(CREATED_TIME) as int))) = '2012-07-09'
    DISTRIBUTE BY BUYER_ID
    SORT BY BUYER_ID, CREATED_TIME desc
) T1
WHERE rank(BUYER_ID) < 5)

そしてTestingTable2、このクエリで-

(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 where to_date(from_unixtime(cast(PROD_AND_TS.TIMESTAMPS as BIGINT))) = '2012-07-09')
4

4 に答える 4

2

NOT INDBMS の制限のために投稿されたクリーンなソリューションを使用できない場合@eggyal、別のオプションとして、元のユニオンを完全に複製し、それらの結果をLEFT JOIN.

次のステートメントをsqlFiddleに適用すると、必要な結果が返されます。

SQL ステートメント

SELECT * 
FROM(
    SELECT *
    FROM TestingTable1 A
    JOIN TestingTable2 B ON A.BUYER_ID = B.USER_ID AND B.LAST_TIME = A.Created_TIME 
    WHERE B.PRODUCT_ID <> A.ITEM_ID
    UNION ALL
    SELECT * 
    FROM TestingTable1 A
    INNER JOIN TestingTable2 B ON A.BUYER_ID = B.USER_ID AND B.PRODUCT_ID = A.ITEM_ID  
    WHERE B.LAST_TIME <> A.Created_TIME      
 ) X
UNION ALL
SELECT A.*, NULL, NULL, NULL
FROM   TestingTable1 A
       LEFT OUTER JOIN (
            SELECT *
            FROM TestingTable1 A
            JOIN TestingTable2 B ON A.BUYER_ID = B.USER_ID AND B.LAST_TIME = A.Created_TIME 
            WHERE B.PRODUCT_ID <> A.ITEM_ID
            UNION ALL
            SELECT * 
            FROM TestingTable1 A
            INNER JOIN TestingTable2 B ON A.BUYER_ID = B.USER_ID AND B.PRODUCT_ID = A.ITEM_ID  
            WHERE B.LAST_TIME <> A.Created_TIME      
       ) X ON A.BUYER_ID = X.BUYER_ID AND A.ITEM_ID = X.ITEM_ID
WHERE  X.BUYER_ID IS NULL
于 2012-07-13T08:04:54.470 に答える
1

SQL で記述されたこのコードを試してください。私はすでにSQL Fiddleでこれをテストしました。

 SELECT 
 tt1.buyer_id,tt1.item_id,tt1.created_time,
 tt2.user_id,tt2.product_id,tt2.last_time
 FROM 
 testingtable1 tt1 LEFT OUTER JOIN
 testingtable2 tt2 ON
 tt1.buyer_id = tt2.user_id
 AND 
 tt1.item_id = tt2.product_id
 AND
 tt1.created_time = tt2.last_time
于 2012-07-13T06:13:10.523 に答える
1

この回答は、https ://stackoverflow.com/a/11440651/1166147 のコメント リクエストに対する回答です。
私は実際にあなたが表示している正確な出力を作成する他の2つの複製でこれに対する答えをあなたに与えました. これは私がここに書いた最初のクエリです: https://stackoverflow.com/a/11440539/1166147 であり、ここで2回言及され説明されています: https://stackoverflow.com/a/11398990/1166147

クエリを変更して自分のものに戻し、SQLFiddle で実行しました。

ここに画像の説明を入力

ただし、要件は進化しており、LEFT JOINTestingTable1 が本当に常に正確なデータであるかどうかを実行できるようになりました。

SELECT *
FROM TestingTable1 A
LEFT JOIN TestingTable2 B ON A.BUYER_ID = B.USER_ID AND (B.LAST_TIME = A.Created_TIME  OR B.PRODUCT_ID = A.ITEM_ID)

コメントのために編集

模擬シナリオ

SCENARIO||       TABLE1           ||           TABLE2
----------------------------------------------------------
SCENARIO||  BUYER  ITEM      TIME ||  USER   PRODUCT  TIME
1       ||    1     A        09   ||   1     Z        09
2       ||    1     B        10   ||   NO RECORD IN TABLE 2
3       ||    1     C        10   ||   1     C        02
4       ||    1     D        12   ||   NO RECORD IN TABLE 2
5       ||    1     E        01   ||   1     E        01
6       ||   NO RECORD IN TABLE 1 ||   1     Y        05      

あなたは SQL ソリューションを求めていますが、実際には SQL の問題ではありません。与えられた有効な SQL の回答は、自分の環境では使用できないため除外し、同じ質問をもう一度開き直します。これは HQL/HIVE に関する質問です。はい、いくつかの類似点がありますが、いくつかの違いがあります。

テストする方法がなく、SQLFiddle もこれをテストするのに有効ではありませんが、HQL はこのようなものをサポートするようです。select ISNULL* COALESCE. これにより、結果が「マージ」され、そこに null 以外の値があった場合、null でない方の値が返されます。私はHQLがISNULLをサポートしていると信じています:

select * --BUYER_ID, isNull(B.USER_ID,C.USER_ID)
from
(select BUYER_ID,ITEM_ID ,Created_TIME  from TestingTable1) a
left join
(SELECT USER_ID,PRODUCT_ID, last_time
  FROM TestingTable2 ) b on(a.BUYER_ID = b.user_id and B.last_time =   A.Created_TIME)
left join
(SELECT USER_ID,PRODUCT_ID, last_time
  FROM TestingTable2 ) c on(a.BUYER_ID = c.user_id and c.PRODUCT_ID = A.ITEM_ID)

これは、いくつかのアイデアを提供する可能性のあるさらに別の TSQL の回答です。これを TSQL で使用することはありませんが、実際には機能します。

SELECT A.BUYER_ID,A.ITEM_ID,CREATED_TIME,COALESCE(B.USER_ID,X.USER_ID,Y.USER_ID),
COALESCE(B.PRODUCT_ID,X.PRODUCT_ID,Y.PRODUCT_ID)
,COALESCE(B.last_time,X.last_time,Y.last_time)
FROM TestingTable1 A
LEFT JOIN TestingTable2 B ON A.BUYER_ID = B.USER_ID AND B.PRODUCT_ID = A.ITEM_ID
AND B.last_time = A.Created_TIME
LEFT JOIN( SELECT USER_ID,PRODUCT_ID, last_time
  FROM TestingTable1 A
  LEFT JOIN TestingTable2 B ON A.BUYER_ID = B.USER_ID AND B.last_time = A.Created_TIME 
  WHERE  ISNULL(B.PRODUCT_ID,0) <> A.ITEM_ID AND B.USER_ID IS NOT NULL) X ON
  X.USER_ID = A.BUYER_ID AND A.Created_TIME = X.last_time
LEFT JOIN( SELECT USER_ID,PRODUCT_ID, last_time
FROM TestingTable1 A
LEFT JOIN TestingTable2 B ON A.BUYER_ID = B.USER_ID AND ISNULL( B.PRODUCT_ID,0) =   A.ITEM_ID  
WHERE  B.last_time <> A.Created_TIME AND B.USER_ID IS NOT NULL) Y ON
A.BUYER_ID = Y.USER_ID AND A.ITEM_ID = Y.PRODUCT_ID
于 2012-07-13T19:09:14.373 に答える
0

あなたが探しているのは完全外部結合のようです。使用しているデータベースのタイプが投稿に表示されなかったため、正確な構文を投稿することはできませんが、このリンクは正しい方向を示している可能性があります。

http://www.w3resource.com/sql/joins/perform-a-full-outer-join.php

具体的には、下の図を見てください。

于 2012-07-13T04:59:38.373 に答える