Oracle SQL—消除联接上不相等的值
下面是我的表的外观:两个表在所有3列上都有一个复合主键。第二个ID不会在这两个表中重复。这显然不是由DB约束强制执行的,而是由前端的业务规则强制执行的Oracle SQL—消除联接上不相等的值,sql,oracle,Sql,Oracle,下面是我的表的外观:两个表在所有3列上都有一个复合主键。第二个ID不会在这两个表中重复。这显然不是由DB约束强制执行的,而是由前端的业务规则强制执行的 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|Ema
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上连接,其中电子邮件在所有出现的primaryid上都不同
对于PrimaryID=1:
表1有两行,表2有一行。但表2中的一封邮件和表1中的一封邮件是一致的,所以我不想把它退回。这是我的问题,但这并不能消除上面的重复,这是我需要的
SELECT DISTINCT T1.SECONDARYID, T2.SECONDARYID
FROM TABLE1 T1 INNER JOIN TABLE2 T2 ON T1.PRIMARYID = T2.PRIMARYID
AND T1.EMAIL <> T2.EMAIL;
因此,您希望从一个表中获取所有记录,并从ID字段相等的另一个表中查找所有此类记录,但第二个表中不存在具有相同电子邮件的记录 我会尝试以下几点:
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能拿出一个好的查询计划)。不过,这应该很容易理解。因此,您希望从一个表中获取所有记录,并从另一个表中查找ID字段相等的所有此类记录,但第二个表中没有具有相同电子邮件的记录 我会尝试以下几点:
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能拿出一个好的查询计划)。不过,这应该很容易理解。您需要识别两个表中至少有一封相同电子邮件的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
)
;
您需要标识两个表中至少有一个相同电子邮件的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
)
;
下面是另一种不需要两次查询两个表的方法:
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()
——您必须更改最终过滤器以反映这一点)为所有行输出“Y”,如果其中至少有一行具有匹配的电子邮件地址
然后,只需过滤掉存在“Y”的行。还有另一种方法,无需两次查询两个表:
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()
——您必须更改最终过滤器以反映这一点)为所有行输出“Y”,如果其中至少有一行具有匹配的电子邮件地址
然后,只需过滤掉存在“Y”的行。两个表中的PrimaryID集是否相同?如果不是,您希望如何处理仅显示在第一个表中而不显示在第二个表中的主ID?是。也一样。如果不是,因为我加入的primaryid相同,我将忽略它。两个表中的primaryid集是否相同?如果不是,您希望如何处理仅显示在第一个表中而不显示在第二个表中的主ID?是。也一样。如果不是,因为我加入的primaryid是一样的,我会忽略它。