加入两个表并从两个表中获取输出

时间:2012-07-11 08:10:26

标签: sql join group-by

  

可能重复:
  SQL Query JOIN with Table

如果这是TestingTable1中的数据

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

如果这是TestingTable2中的以下数据

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

我需要在TestingTable2TestingTable1上将BUYER_IDUSER_ID进行比较。我需要看一下,如果BUYER_IDUSER_ID匹配,那么我需要将ITEM_IDPRODUCT_IDCREATED_TIMELAST_TIME进行比较,如果有的话与TestingTable2中的任何一个或两者中的TestingTable1进行比较后,TestingTable1不匹配,那么我需要显示结果。

因此,如果你看一下上面的例子 - 基本上我有三个场景

  1. 首先 - 在ITEM_ID中,第一行PRODUCT_IDTestingTable2的第一行中的CREATED_TIME不匹配,但LAST_TIME与{匹配} {1}}表示两个表中的第一行
  2. 其次 - 在TestingTable1中,第二行CREATED_TIMELAST_TIME第二行中的TestingTable2不匹配,但ITEM_ID与{匹配} {1}}表示两个表中的第二行
  3. 第三 - 在PRODUCT_ID中,第三行TestingTable1ITEM_ID不匹配且PRODUCT_IDCREATED_TIME不匹配,因此在它们的第三行与LAST_TIME第三行不匹配。
  4. 因此,在将TestingTable1TestingTable2进行比较时,我需要介绍这三种情况。 TestingTable1是MAIN表,通过该表总是需要进行比较,这意味着TestingTable1中的数据始终是准确的。

    所以我需要显示这样的结果,考虑到上面的例子,如果不匹配其中任何一个或两个 - TestingTable1数据然后在它旁边相同的TestingTable1数据,这样我就可以与TestingTable2

    相比,查看TestingTable1中的值
    TestingTable2

    所以我写了一个查询,我认为它将涵盖我的三个场景,但只有BUYER_ID | ITEM_ID | CREATED_TIME | USER_ID | PRODUCT_ID | LAST_TIME -----------+-----------------+---------------------------+----------------+--------------------+----------------------- 1345653 151851771618 2012-07-09 19:57:33 1345653 150851771618 2012-07-09 19:57:33 1345653 110909316904 2012-07-09 21:29:06 1345653 110909316904 2012-07-09 22:29:06 1345653 221065796761 2012-07-09 19:31:48 1345653 221165796761 2012-07-09 12:31:48 而不是First Two。我是否能够实现第三种情况而感到困惑?

    Third One

    任何建议都将受到赞赏。

    更新: -

    快速更新我最初的想法。因为我意识到我的第三种情况几乎没有问题。

    首先在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.PRODUCTID <> A.ITEM_ID UNION ALL SELECT * FROM TestingTable1 A INNER JOIN TestingTable2 B ON A.BUYER_ID = B.USER_ID AND B.PRODUCTID = A.ITEM_ID WHERE B.t1time <> A.Created_TIME ) X 中,我按TestingTable1BUYER_ID对表进行排序(ORDER BY),与CREATED_TIME相同,我正在使用{{1}进行排序}和TestingTable2我正在进行比较,确保数据属于某一天的USER_IDLAST_TIME

4 个答案:

答案 0 :(得分:1)

您可以使用non exists子句在一个表中查找另一个中不匹配的行。使用union,您可以为另一个表重复此操作:

select  'missing in t2', *
from    TestingTable1 t1
where   not exists
        (
        select  *
        from    TestingTable2 t2
        where   t1.buyer_id = t2.user_id
                and t1.item_id = t2.product_id
                and t1.created_time = t2.last_time
        )
union all
select  'missing in t1', *
from    TestingTable2 t2
where   not exists
        (
        select  *
        from    TestingTable1 t1
        where   t1.buyer_id = t2.user_id
                and t1.item_id = t2.product_id
                and t1.created_time = t2.last_time
        )

Live example at SQL Fiddle.

答案 1 :(得分:1)

with C as
(
  select *
  from TestingTable1 A
    inner join TestingTable2 B
      on A.BUYER_ID = B.USER_ID and
         B.LAST_TIME = A.Created_TIME and
         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 and
         B.LAST_TIME <> A.CREATED_TIME
)
select *
from C
union all
select *
from TestingTable1 A
  inner join TestingTable2 B
    on A.BUYER_ID = B.USER_ID and
       A.CREATED_TIME <> B.LAST_TIME and
       A.ITEM_ID <> B.PRODUCT_ID
where not exists (select *
                  from C
                  where A.BUYER_ID = C.BUYER_ID and
                        A.ITEM_ID = C.ITEM_ID and
                        A.CREATED_TIME = C.CREATED_TIME) and
      not exists (select *
                  from C
                  where B.USER_ID = C.USER_ID and
                        B.PRODUCT_ID = C.PRODUCT_ID and
                        B.LAST_TIME = C.LAST_TIME);

SQL Fiddle

答案 2 :(得分:0)

您可以获得的最接近的是匹配TestingTable1中的所有行,而TestingTable2中的所有行与TestingTable2中的每个可能不匹配的行匹配。

像这样(未经测试,但希望你能得到这个想法):

SELECT *
FROM TestingTable1 AS T1
INNER JOIN TestingTable2 AS T2 ON T1.BUYER_ID = T2.USER_ID
    AND
    (
        (
            (T1.ITEM_ID = T2.PRODUCT_ID AND T1.CREATED_TIME <> T2.LAST_TIME)
            OR (T1.ITEM_ID <> T2.PRODUCT_ID AND T1.CREATED_TIME = T2.LAST_TIME)
            OR 
            (
                T1.ITEM_ID <> T2.PRODUCT_ID AND T1.CREATED_TIME <> T2.LAST_TIME
                AND NOT EXISTS(SELECT 1
                       FROM TestingTable2 AS T2a
                       INNER JOIN TestingTable1 AS T1a ON T2a.USER_ID = T1a.BUYER_ID
                       AND 
                       (
                           (T1a.ITEM_ID = T2a.PRODUCT_ID AND T1a.CREATED_TIME <> T2a.LAST_TIME)
                           OR (T1a.ITEM_ID <> T2a.PRODUCT_ID AND T1a.CREATED_TIME = T2a.LAST_TIME)
                       )
                       WHERE T1a.BUYER_ID = T1.BUYER_ID
                       AND (T2a.PRODUCT_ID <> T2.PRODUCT_ID OR T2a.LAST_TIME <> T2.LAST_TIME)                       
                      )
            )
        )
    )

也就是说,如果TestingTable2中还有一行:

USER_ID  |   PRODUCT_ID   |    LAST_TIME
---------+----------------+-----------------------
1345653     333333333333      2012-07-09 05:27:18

您的结果集如下所示:

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

请注意,对于每个错误的PRODUCT_ID或LAST_TIME,假设您在TestingTable2 中只有一个且只有一个相关行,则都是。否则你会得到各种疯狂的笛卡尔产品比赛!为了避免这种情况,您需要确定一个或两个表的排序,以确定首先匹配哪一行。

例如,尝试将符合方案1和2的以下行添加到TestingTable2,看看会发生什么:

USER_ID  |   PRODUCT_ID   |    LAST_TIME
---------+----------------+-----------------------
1345653     110909316904      2012-07-09 19:57:33

答案 3 :(得分:0)

整个尝试都存在一个主要问题。

由于UserID / BuyerID在每一行都相同,因此查询会将来自TestingTable1的每一行与来自TestingTable2的每一行进行比较。

前两个比较对你有用,这只是巧合; 如果您有多个具有类似CREATED_TIME的行(即使具有不同的ITEM_ID),它们也会相互比较。

我建议的是:
为每个表添加primary key,并为其添加foreign key 这样,您就可以将TestingTable1中的每一行与TestingTable2中的等效项进行比较,而不会产生“笛卡尔积”。