Brett
Brett

Reputation: 20049

Using LEFT JOIN to returns rows that don't have a match

I have a situation where we have a table that contains all the items, if the item was sold it has an entry in another table.

I am trying to get all the items returned that have not been sold, but it doesn't seem to work.

I have this SQL:

SELECT a.auction_id FROM auctions AS a 
LEFT JOIN winners AS w ON a.auction_id=w.auction_id AND w.winner_id IS NULL
WHERE a.owner_id=1234567 AND a.is_draft=0 AND a.creation_in_progress=0;

I thought this would only return items from the auctions table that don't have a matched entry in the winners table since I am doing AND w.winner_id IS NULL.

However it seems to still return the same amount of rows as it does when I leave off AND w.winner_id IS NULL.

Upvotes: 0

Views: 71

Answers (1)

Brian DeMilia
Brian DeMilia

Reputation: 13248

SELECT a.auction_id
  FROM auctions AS a
  LEFT JOIN winners AS w
    ON a.auction_id = w.auction_id
 WHERE a.owner_id = 1234567
   AND a.is_draft = 0
   AND a.creation_in_progress = 0
   AND w.winner_id IS NULL

This belongs in the WHERE clause:

   AND w.winner_id IS NULL

Criteria on the outer joined table belongs in the ON clause when you want to ALLOW nulls. In this case, where you're filtering in on nulls, you put that criteria into the WHERE clause. Everything in the ON clause is designed to allow nulls.

Here are some examples using data from a question I answered not long ago:

Proper use of where x is null: http://sqlfiddle.com/#!2/8936b5/2/0

Same thing but improperly placing that criteria into the ON clause: http://sqlfiddle.com/#!2/8936b5/3/0

(notice the FUNCTIONAL difference, the result is not the same, because the queries are not functionally equivalent)

Upvotes: 3

Related Questions