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 中不存在,那么我需要在输出中显示它们,因为TestingTable1我有这个数据但对应于TestingTable2我有这个数据(这将是错误的数据),这样我就可以看到不匹配的内容以及缺少的数据。

我需要TestingTable2TestingTable1onBUYER_ID和进行比较USER_ID。我需要看看,如果BUYER_IDUSER_ID匹配,那么我需要比较ITEM_ID和,如果在PRODUCT_ID与其中一个或两个比较之后存在不匹配,那么我需要显示结果。CREATED_TIMELAST_TIMETestingTable2TestingTable1

所以如果你看上面的例子——我基本上有三个场景

  1. 首先TestingTable1,在第一行与第一行ITEM_ID匹配PRODUCT_IDTestingTable2但与两个表中的第一行CREATED_TIME不匹配LAST_TIME
  2. 其次TestingTable1,在第二行与第二行CREATED_TIME匹配LAST_TIMETestingTable2但与两个表中的第二行ITEM_ID不匹配PRODUCT_ID
  3. 第三 - 在TestingTable1中,最后两行(行)根本不存在TestingTable2。我写的查询中没有涵盖这种情况。我希望在我的查询中也有这种情况

TestingTable2因此,这是我在与TestingTable1always进行比较时需要涵盖的三种情况。并且TestingTable1是需要始终进行比较的主表,因此这意味着其中的数据TestingTable1始终是准确的。

TestingTable2因此,如果不匹配其中任何一个或根本不存在数据,TestingTable1则我需要显示如下结果TestingTable2TestingTable1TestingTable2

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我上面提到的查询,它工作正常,我会得到像上面一样的输出,从输出中留下最后两行。但我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 相关的问题,但这仅涵盖了我的两个场景,而不是我在此查询中需要的第三个场景。

更新:- 我不能使用SQLNOT INNOT EXISTS语法,因为我正在使用 Hive 并且 Hive 不支持NOT INNOT EXISTS所以我需要一些其他方法来处理这个问题。

我只需要使用我的查询来修改它以适用于第三场景,因为这样 Hive 将支持 SQL 语法。

下面是我的SQL Fiddle,它满足了我上面的两个场景,但不是第三种场景。谁能帮我修改我的查询以适用于第三种情况?

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

如果由于 DBMS 限制而无法使用NOT IN或发布的干净解决方案@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 ,这里提到并解释了两次: https ://stackoverflow.com/a/11398990/1166147

我将您的查询修改回我的并在您的 SQLFiddle 中运行它:

在此处输入图像描述

不过,您的要求已经发生了变化,看起来您现在可以做一个LEFT JOINif TestingTable1 真的总是准确的数据。

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 问题。是的,有一些相似之处,但也有一些不同之处。

看起来 HQL 会支持这样的东西,尽管我无法测试,SQLFiddle 也不能用于测试。您将必须弄清楚如何使用ISNULLHQL COALESCE,如选择 * 旁边的评论所示。如果那里有非空值,这将“合并”结果并返回非空值。我确实相信 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 回答