2012-07-11 64 views
4

可能重复:
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 

我需要比较TestingTable2TestingTable1BUYER_IDUSER_ID。我需要看到,如果BUYER_IDUSER_ID得到匹配的话,我需要与PRODUCT_IDCREATED_TIMELAST_TIME比较ITEM_ID,如果有与TestingTable1在他们或他们两人中的任何一个进行比较后TestingTable2不匹配的话,我需要证明结果。

所以,如果你看一下上面的示例 - 我有三个方案基本

  1. Firstly-在TestingTable1,在第一行ITEM_ID不是TestingTable2第一行与PRODUCT_ID匹配,但CREATED_TIME与匹配LAST_TIME两者的表中的第一行
  2. Secondly-在TestingTable1,在第二行中CREATED_TIME没有的TestingTable2第二行中与LAST_TIME匹配但ITEM_ID与匹配对于第二行中两个表
  3. Thirdly-在TestingTable1,在第三行中ITEM_ID不与PRODUCT_ID匹配并且还CREATED_TIME不与LAST_TIME匹配,所以第三行中两者不与TestingTable1第三匹配行。

所以这三种情况我需要覆盖,而总是比较TestingTable2TestingTable1TestingTable1是主表,通过它,总是需要进行比较,所以它意味着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  

任何建议,将不胜感激。

更新: -

只是一个快速更新我最初想的事。我意识到我的第三种情况存在一些问题。

首先在TestingTable1,我排序(ORDER BY)由BUYER_IDCREATED_TIME和同样与TestingTable2我与USER_IDLAST_TIME排序表,我通过确保数据做比较,属于BUYER_IDUSER_ID上给定的一天。

回答

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

+0

感谢Mikael提供的详细解决方案。我发布了另一个类似的问题,在这个问题中,我需要使用我写的查询来实现我的第三个场景,因为我的查询正在为所有这两种场景工作,我只需要为第三种场景修改它。还有第三个场景问题,我之前没有问过。 [http://stackoverflow.com/questions/11464273/multi-join-in-a-single-sql-query](http://stackoverflow.com/questions/11464273/multi-join-in-a-single- SQL查询)。任何帮助将不胜感激。 – ferhan 2012-07-13 05:49:01

0

你可以在TestingTable2每一个可能不匹配的行匹配TestingTable1所有行,而不在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 
+0

我已经更新了,我最初是想用几个指针的问题。 – ferhan 2012-07-11 09:01:44

+0

感谢lc.for详细的解决方案。我发布了另一个类似的问题,其中我需要实现第三个场景,第三个场景完全不同于我的上述问题,并且需要使用我写的查询来实现第三个场景,因为我的查询正在为所有这两种场景工作,只需要修改它的第三种情况。还有第三个场景问题,我之前没有问过。 [http://stackoverflow.com/questions/11464273/multi-join-in-a-single-sql-query](http://stackoverflow.com/questions/11464273/multi-join-in-a-single- SQL查询)。任何帮助将不胜感激。 – ferhan 2012-07-13 05:50:14

0

有与整个尝试的一个主要问题。

由于用户ID/BuyerID是每一行中的相同,该查询从TestingTable1比较每行从TestingTable2每一行

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

我推荐的是这样的:
为每个表添加primary key,并且将连接它们的foreign key
通过这种方式,您将能够将TestingTable1中的每一行与TestingTable2中的等效内容进行比较,而不会产生“笛卡尔积”。

+0

我已经用几个指针更新了我的问题,我最初的想法是什么。 – ferhan 2012-07-11 08:51:55

+0

@rjchar你是说第三种情况只在同一天检查差异吗? – 2012-07-11 09:27:03

+0

所有这三种情况都将在特定的一天进行检查。首先,我将在'BUYER_ID'和'CREATED_TIME'上对给定日期的'Table1'进行排序,并且'Table1'中每个'BUYER_ID'只有5个条目。同样,我会在'USER_ID'和'LAST_TIME'上对给定日期的'Table2'进行排序,并且'Table2'中每个'USER_ID'只有5个条目。然后我会在两张桌子上进行比较,因为所有事情都会按时间进行排序,然后我可以进行比较。 – ferhan 2012-07-11 18:14:59

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.

+0

虽然这并没有做任何事情来关联这两个表,这是我认为OP想要的。 – 2012-07-11 08:44:26

+0

当我试图打开它时,SQL小提琴有问题。 – ferhan 2012-07-11 08:52:36

+0

@rjchar - 你有什么样的麻烦?你用什么浏览器? (我是SQL Fiddle BTW的拥有者) – 2012-07-11 15:28:04