Mike Zornek <[EMAIL PROTECTED]> wrote on 01/20/2005 11:01:38 AM: > I have the following query which will get me all of the emails for my > current membership: > > SELECT email.email_address > FROM member, email > WHERE > member.member_primary_email_id = email.email_id > AND member.member_standing != "Dropped" > ORDER BY email.email_address > > I also have a query which will get me the email addresses of anyone who has > updated their profile (and thus has a row in updatehistory) > > SELECT DISTINCT email.email_address > FROM member, email, updatehistory > WHERE > member.member_primary_email_id = email.email_id > AND member.member_standing != "Dropped" > AND member.member_id = updatehistory.member_id_editor > ORDER BY email.email_address; > > How would I get the emails for every member who does NOT have a row in > updatehistory? > > ~ Mike > ----- > Mike Zornek > Web Designer, Media Developer, Programmer and Geek > Personal site: <http://MikeZornek.com> >
First, I need to you recognize that listing tables with commas in the FROM clause creates an implicit INNER JOIN between the tables. That means that your query SELECT DISTINCT email.email_address FROM member, email, updatehistory WHERE member.member_primary_email_id = email.email_id AND member.member_standing != "Dropped" AND member.member_id = updatehistory.member_id_editor ORDER BY email.email_address; IS EQUIVALENT to this more explicitly defined query: SELECT DISTINCT email.email_address FROM member INNER JOIN email ON member.member_primary_email_id = email.email_id INNER JOIN updatehistory ON member.member_id = updatehistory.member_id_editor WHERE member.member_standing != "Dropped" ORDER BY email.email_address; In order to detect non-matches between two tables, you perform an outer join between them and look for the records that don't match. They will be easy to spot because the engine will put NULLs into every column of the "optional" table for those rows that don't match up with the "required" table. In a LEFT JOIN, the table on the left of the clause is the required table and the one on the right is the optional table. Reverse that for RIGHT JOINs. With that knowledge in hand, we will now change the query to detect which rows of member (required) do not match any rows in updatehistory (optional). We change the JOIN on that table from INNER JOIN to LEFT JOIN and look for NULL values where there shouldn't be any by adding another condition to the WHERE clause (they should only exist if rows between the two tables didn't meet your ON conditions(s), correct?). We don't need to change anything else. SELECT DISTINCT email.email_address FROM member INNER JOIN email ON member.member_primary_email_id = email.email_id LEFT JOIN updatehistory ON member.member_id = updatehistory.member_id_editor WHERE member.member_standing != "Dropped" AND updatehistory.member_id_editor IS NULL ORDER BY email.email_address; Shawn Green Database Administrator Unimin Corporation - Spruce Pine