tags:

views:

414

answers:

5

I am going to build a table called donotemail that will contain the email addresses of people who ask to be removed from our email list. I have another table called users with an email column. How can I select all the emails from users but only if the email address is not in the donotemail table?

Thanks!

+2  A: 
 select u.email from users u where u.email not in (select email from donotemail)

OR

select u.email from users u inner join donotemail d on u.email != d.email

EDIT: The join doesn't work

Byron Whitlock
"inner join donotemail d on u.email != d.email" ?? you'll join on every other user won't you ?
streetpc
yeah, but that will be a null set since donoteamail should have email as its primary key
Byron Whitlock
what ? u = [[email protected], [email protected], [email protected]], donotemail = [a, b] => inner join on different = [a/b, b/a, c/a, c/b] no ?
streetpc
Byron: Er... are you sure? If email is primary key in both tables, u.email != d.email will be true for n or n-1 rows in the second table, where n is the number of rows in the second table.
R. Bemrose
@Streetpc yes, I think you're right, I was struggling to wrap my mind around what was wrong with this. I think you will get u x d-1 results, which isn't exactly what you want
Mike Houston
Yes you guys are right. It doesn't do what it should.
Byron Whitlock
A: 
select email from users where email not in (select email from donotemail)
AlbertEin
A join is way faster than a sub-select
artemb
if you have a NULL email in donotemail, it will return an empty set
streetpc
@artemb it depends, subselect can be executed only once if the query optimizer understands that it should not be refetched
streetpc
@streetpc: According to the MySQL manual, IN subqueries are converted to correlated subqueries: http://dev.mysql.com/doc/refman/5.0/en/subquery-restrictions.html
R. Bemrose
yes, so slow here too...
streetpc
+1  A: 
SELECT email FORM users u WHERE NOT EXISTS(
    SELECT 1 FROM no_mail_users nmu
    WHERE nmu.id = u.id
)
streetpc
correlated subqueries are extremely, EXTREMELY slow, as you end up having one query per row in the outer table.
R. Bemrose
+1  A: 

Why not just add another column to your email table, labeled Active, when set to 1 it is currently emailing, and when set to 0 it no longer emails, then you can just select and filter based on that switch?

Cheers

Frederico
+2  A: 

Try

SELECT Email.address
FROM Email LEFT OUTER JOIN DoNotMail on Email.address = DoNotMail.address
WHERE DoNotMail.address is null

It avoids needing a subquery.

Mike Houston
Ha, I was just writing a similar query when I saw a new answer had been posted. Good thing I checked before submitting.
R. Bemrose
Did seem to be a flood of answers - the four before me were all posted while I wrote my answer :)
Mike Houston
+1 this one is performant and elegant
streetpc