سؤال

I have a problem formulating a MySQL query to do the following task, although I have seen similar queries discussed here, they are sufficiently different from this one to snooker my attempts to transpose them. The problem is (fairly) simple to state. I have three tables, 'members', 'dog_shareoffered' and 'dog_sharewanted'. Members may have zero, one or more adverts for things they want to sell or want to buy, and the details are stored in the corresponding offered or wanted table, together with the id of the member who placed the ad. The column 'id' is unique to the member, and common to all three tables. The query I want is to ask how many members have NOT placed an ad in either table.

I have tried several ways of asking this. The closest I can get is a query that doesn't crash! (I am not a MySQL expert by any means). The following I have put together from what I gleaned from other examples, but it returns zero rows, where I know the result should be greater than zero.

SELECT id 
  FROM members 
 WHERE id IN (SELECT id 
                FROM dog_sharewanted 
               WHERE id IS NULL) 
   AND id IN (SELECT id 
                FROM dog_shareoffered 
               WHERE id IS NULL)

THis query looks pleasingly simple to understand, unlike the 'JOIN's' I've seen but I am guessing that maybe I need some sort of Join, but how would that look in this case?

هل كانت مفيدة؟

المحلول

If you want no ads in either table, then the sort of query you are after is:

SELECT id
FROM members
WHERE id NOT IN ( any id from any other table )

To select ids from other tables:

SELECT id
FROM <othertable>

Hence:

SELECT id
FROM members
WHERE id NOT IN (SELECT id FROM dog_shareoffered)
 AND  id NOT IN (SELECT id FROM dog_sharewanted)

I added the 'SELECT DISTINCT' because one member may put in many ads, but there's only one id. I used to have a SELECT DISTINCT in the subqueries above but as comments below mention, this is not necessary.

If you wanted to avoid a sub-query (a possible performance increase, depending..) you could use some LEFT JOINs:

SELECT members.id
FROM members
LEFT JOIN dog_shareoffered
 ON dog_shareoffered.id = members.id
LEFT JOIN dog_sharewanted
 ON dog_sharewanted.id = members.id
WHERE dog_shareoffered.id IS NULL
  AND dog_sharewanted.id IS NULL

Why this works:

It takes the table members and joins it to the other two tables on the id column. The LEFT JOIN means that if a member exists in the members table but not the table we're joining to (e.g. dog_shareoffered), then the corresponding dog_shareoffered columns will have NULL in them.

So, the WHERE condition picks out rows where there's a NULL id in both dog_shareoffered and dog_sharewanted, meaning we've found ids in members with no corresponding id in the other two tables.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top