Oracle SQL - 消除联接

时间:2017-11-17 16:13:37

标签: sql oracle

以下是我的表格外观:两个表都在所有3列上都有一个复合主键。 SecondaryId不会从这两个表中重复出来。这显然不是由数据库约束强制执行,而是由前端的业务规则强制执行。

Table1:
PrimaryID|SecondaryID|Email
1   9999    ABC@GMAIL.COM
1   9999    DEF@GMAIL.COM
2   8888    CCC@GMAIL.COM
3   7777    CBA@GMAIL.COM

Table2:
PrimaryID|SecondaryID|Email
1   1111    ABC@GMAIL.COM
2   2222    XYZ@GMAIL.COM
3   3333    CBA@GMAIL.COM

我希望返回两个表中的secondaryid,加入相同的primaryid,其中所有主要ID的电子邮件都不同。

对于PrimaryID = 1: Table1有两行,表2有一行。但是来自table2的那封电子邮件与table1上的那封电子邮件匹配,所以我不想要回来。这是我的查询,但这并不能消除我需要的上述副本。

 SELECT DISTINCT T1.SECONDARYID, T2.SECONDARYID 
    FROM TABLE1 T1 INNER JOIN TABLE2 T2 ON T1.PRIMARYID = T2.PRIMARYID
    AND T1.EMAIL <> T2.EMAIL;

返回

9999    1111
8888    2222

3 个答案:

答案 0 :(得分:1)

因此,您希望从一个表中获取所有记录,并从另一个表中查找ID字段相同的所有此类记录,但在第二个表中使用相同的电子邮件不存在记录。< / p>

我尝试了以下几点:

select one.*, another.*
from one, another
where
  one.id = another.id and
  not exists (
    select 1 
    from another as another_again
    where 
      another_again.id = one.id and
      another_again.email = one.email
  )

这可能不是严格来说最快的查询(希望Oracle可以提出一个不错的查询计划)。不过应该很容易理解。

答案 1 :(得分:1)

您需要确定两个表中至少有一个共同电子邮件的ID。一种方法是在子查询中加入primaryid和email。下面的解决方案可能不是最有效的,但它可以完成这项工作。

select t1.primaryid,
       t1.secondaryid as secondaryid_in_t1,
       t2.secondaryid as secondaryid_in_t2
from   table1 t1 join table2 t2 
                 on t1.primaryid = t2.primaryid
where  t1.primaryid not in (
         select a.primaryid 
         from   table1 a join table2 b
                          on a.primaryid = b.primaryid and a.email = b.email
       )
;

答案 2 :(得分:1)

这是另一种方法,无需两次查询两个表:

WITH table1 AS (SELECT 1 PrimaryID, 9999 SecondaryID, 'ABC@GMAIL.COM' Email FROM dual UNION ALL
                SELECT 1 PrimaryID, 9999 SecondaryID, 'DEF@GMAIL.COM' Email FROM dual UNION ALL
                SELECT 2 PrimaryID, 8888 SecondaryID, 'CCC@GMAIL.COM' Email FROM dual UNION ALL
                SELECT 3 PrimaryID, 7777 SecondaryID, 'CBA@GMAIL.COM' Email FROM dual),
     table2 AS (SELECT 1 PrimaryID, 1111 SecondaryID, 'ABC@GMAIL.COM' Email FROM dual UNION ALL
                SELECT 2 PrimaryID, 2222 SecondaryID, 'XYZ@GMAIL.COM' Email FROM dual UNION ALL
                SELECT 3 PrimaryID, 3333 SecondaryID, 'CBA@GMAIL.COM' Email FROM dual)
SELECT primaryid,
       t1_secondaryid,
       t2_secondaryid
FROM   (SELECT coalesce(t1.primaryid, t2.primaryid) primaryid,
               t1.secondaryid t1_secondaryid,
               t2.secondaryid t2_secondaryid,
               MAX(CASE WHEN t1.email = t2.email THEN 'Y' ELSE 'N' END) OVER (PARTITION BY coalesce(t1.primaryid, t2.primaryid)) same_email_present
        FROM   table1 t1
               FULL OUTER JOIN table2 t2 ON t1.primaryid = t2.primaryid AND t1.email = t2.email)
WHERE  same_email_present != 'Y';

 PRIMARYID T1_SECONDARYID T2_SECONDARYID
---------- -------------- --------------
         2                          2222
         2           8888 

这使用完整的外部联接来拉回所有行,无论它们是否匹配。然后我们可以使用分析函数(我选择MAX()但您可以轻松切换到COUNT()SUM(),如果您愿意 - 您必须更改最终过滤器以反映虽然)输出&#39; Y&#39;对于所有行,如果其中至少有一行具有匹配的电子邮件地址。

然后,只需过滤掉那些有&#39; Y&#39;本。