Reputation: 147
I'm trying to find all internal communications that is purely from/to an organisation and not to any other organisation.
CREATE TABLE emails
(
Id INT,
from_org VARCHAR(50)
);
CREATE TABLE users
(
emailId INT,
FullName VARCHAR(50) NOT NULL,
Organisation VARCHAR(50) NOT NULL
);
INSERT INTO emails (Id, from_org)
VALUES (1, 'ABC Pty Ltd'), (2, 'ABC Pty Ltd'),
(3, 'Point Pty Ltd'), (4,'ABC Pty Ltd');
INSERT INTO users (emailId, FullName, Organisation)
VALUES (1, 'John Smith', 'ABC Pty Ltd'),
(1, 'Maria Jones', 'Point Pty Ltd'),
(2, 'Ben Coria', 'ABC Pty Ltd'),
(3, 'Leo Sen', 'Point Pty Ltd'),
(4, 'Leo Sen', 'Point Pty Ltd');
In this scenario, I want to find all emails that are from 'ABC Pty Ltd' (emails.from_org) and where it's to an internal user (users.Organisation = 'ABC Pty Ltd'). My current query is:
SELECT *
FROM emails
LEFT JOIN users ON emails.Id = users.emailId
WHERE emails.from_org = 'ABC Pty Ltd'
AND users.organisation = 'ABC Pty ltd'
Output:
| Id | from_org | emailId | FullName | Organisation |
+-----+-------------+---------+------------+--------------+
| 1 | ABC Pty Ltd | 1 | John Smith | ABC Pty Ltd |
| 2 | ABC Pty Ltd | 2 | Ben Coria | ABC Pty Ltd |
Expected result:
| Id | from_org | emailId | FullName | Organisation |
+-----+-------------+---------+------------+--------------+
| 2 | ABC Pty Ltd | 2 | Ben Coria | ABC Pty Ltd |
The returned value is because emailId '2' is from_org 'ABC Pty Ltd' and only to 'ABC Pty Ltd' and no other organisation.
sqlfiddle doesn't work for me at the moment.
Upvotes: 1
Views: 542
Reputation: 1405
Here is an another approach, you can first calculate the emailID's that belong to single organization and join it with emails table.
select * from emails e1 join (
select * from users u1 where not exists ( select 1 from users u2 where u1.emailId = u2.emailID and u1.Organisation <> u2.Organisation)) u3
on e1.Id = u3.emailId and e1.from_org = 'ABC Pty Ltd' and Organisation = 'ABC Pty Ltd'
Upvotes: 0
Reputation: 521674
I think not exists logic works nicely here:
SELECT e.Id, e.from_org, u1.emailId, u1.FullName, u1.Organisation
FROM emails e
INNER JOIN users u1 ON u1.emailId = e.Id
WHERE NOT EXISTS (SELECT 1 FROM users u2
WHERE u2.emailId = e.Id AND u2.Organisation <> e.from_org);
Read simply, the above query says to return any email for which we cannot find a user outside of the originating organization which is associated with that email.
Upvotes: 1
Reputation: 35910
You can use NOT EXISTS
as follows:
SELECT *
FROM emails
LEFT JOIN users u ON emails.Id = u.emailId
WHERE emails.from_org = 'ABC Pty Ltd'
AND u.organisation = 'ABC Pty ltd'
AND NOT EXISTS (select 1 from users uu
where uu.emailId = u.emailId and u.organisation <> 'ABC Pty ltd')
Upvotes: 3