Reputation: 349
Here's how my tables look: Both tables have a composite primary key on all 3 columns. And the SecondaryId will not repeat from these two tables. This is obviously not enforced by a DB constraint but by business rules on the front-end.
Table1:
PrimaryID|SecondaryID|Email
1 9999 [email protected]
1 9999 [email protected]
2 8888 [email protected]
3 7777 [email protected]
Table2:
PrimaryID|SecondaryID|Email
1 1111 [email protected]
2 2222 [email protected]
3 3333 [email protected]
I want the secondaryid in both tables returned, joining on the same primaryid where the emails are different on all occurrences of the primary id.
For PrimaryID = 1: Table1 has two rows, table 2 has one row. But that one email from table2 matches with the one on table1 so I don't want that back. Here's my query but that doesn't eliminate the above duplicate which is what I need.
SELECT DISTINCT T1.SECONDARYID, T2.SECONDARYID
FROM TABLE1 T1 INNER JOIN TABLE2 T2 ON T1.PRIMARYID = T2.PRIMARYID
AND T1.EMAIL <> T2.EMAIL;
Returns
9999 1111
8888 2222
Upvotes: 0
Views: 1193
Reputation: 23588
Here's another way without needing to query both tables twice:
WITH table1 AS (SELECT 1 PrimaryID, 9999 SecondaryID, '[email protected]' Email FROM dual UNION ALL
SELECT 1 PrimaryID, 9999 SecondaryID, '[email protected]' Email FROM dual UNION ALL
SELECT 2 PrimaryID, 8888 SecondaryID, '[email protected]' Email FROM dual UNION ALL
SELECT 3 PrimaryID, 7777 SecondaryID, '[email protected]' Email FROM dual),
table2 AS (SELECT 1 PrimaryID, 1111 SecondaryID, '[email protected]' Email FROM dual UNION ALL
SELECT 2 PrimaryID, 2222 SecondaryID, '[email protected]' Email FROM dual UNION ALL
SELECT 3 PrimaryID, 3333 SecondaryID, '[email protected]' 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
This uses a full outer join to pull all rows back regardless of whether they match or not. Then we can use an analytic function (I chose MAX()
but you could easily switch to COUNT()
or SUM()
if you wanted to - you'd have to change the final filter to reflect that though) to output 'Y' for all rows if at least one of them has a matching email address.
Then it's just a matter of filtering out those rows which have a 'Y' present.
Upvotes: 1
Reputation:
You need to identify the id's for which there is at least one email in common in the two tables. One way to do that is to join on primaryid and email in a subquery. The solution below may not be the most efficient, but it will do the job.
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
)
;
Upvotes: 1
Reputation: 40894
So, you want to take all records from one table and find all such records from another table that the ID field is equal, but no record exists in the second table with an equal email.
I'd try something along these lines:
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
)
This might be not strictly the fastest query (hopefully Oracle can come up with a nice query plan). It should be easy to understand, though.
Upvotes: 1