tags:

views:

65

answers:

3

I have a table called 'bandsplusrating' and a table called 'ratings' The table 'bandsplusrating' is filled with bands, the table 'ratings' starts empty.

Both tables have field called 'naam' with which they can be joined. Table 'ratings' has a field called 'fullname'

Multiple Ratings per band (bandsplusrating) will be stored in table 'ratings'

Now i want to display all records from 'bandsplusrating' which havent been rated by a given user (ratings.fullname)

SELECT b.naam, b.stijl
FROM bandsplusrating b
LEFT JOIN ratings r ON b.naam = r.naam
WHERE r.fullname NOT LIKE 'Obama'

This query will still display a record when an other user has rated it.

Im am struggeling for days now, can someone assist me ?

Thanks!

+5  A: 
SELECT    b.naam, b.stijl
FROM      bandsplusrating b
LEFT JOIN ratings r 
ON        b.naam  = r.naam
AND       'Obama' = r.fullname
WHERE     r.naam IS NULL

The trick is, the LEFT JOIN is evaluated before the WHERE. So by first letting the join roll out, any rows from bandplusrating that do not match anything in ratings will yield a NULL-record for ratings (a ratings record with only NULL values). Then, you can filter on that using the WHERE and by demanding that some known mandatory column from ratings IS NULL, you're effectively saying: only those that didn't match.

EDIT:

I just saw OMG Ponies' thorough reply, and decided to add yet another method to do it, which is just a slight variation of the LEFT JOIN solution:

SELECT    b.naam, b.stijl
FROM      bandsplusrating b
LEFT JOIN ratings r 
ON        b.naam  = r.naam
AND       'Obama' = r.fullname
GROUP BY  b.naam, b.stijl
HAVING    COUNT(r.naam) = 0

(Personally I think this one is less good that the prior one)

Roland Bouman
Thanks for the QUICK reply. I have to sleep now, will try it tomorrow in an expanded version and will get back. I did a quick run and it looks promising !
Checkerforth
@rolandThe result of this query produces duplicate fields (naam, stijl etc.)I cannot read $row['naam'] therefore.
Checkerforth
Checkerforth, show me some data that demonstrates it. So, some rows from bandplusrating, ratings, and the result with the duplicates.
Roland Bouman
A: 

The answer to my question here may help you a bit (has some additional explanation that will clarify Roland's answer further).

John at CashCommons
+4  A: 

Using NOT IN:


SELECT b.naam,
       b.stigl
  FROM BANDPLUSRATING b
 WHERE b.naam NOT IN (SELECT r.naam
                        FROM RATINGS r
                       WHERE r.fullname LIKE 'Obama')

Using NOT EXISTS:


SELECT b.naam,
       b.stigl
  FROM BANDPLUSRATING b
 WHERE NOT EXISTS(SELECT NULL
                    FROM RATINGS r
                   WHERE r.naam = b.naam
                     AND r.fullname LIKE 'Obama')

Using LEFT JOIN/IS NULL:


   SELECT b.naam,
          b.stigl
     FROM BANDPLUSRATING b
LEFT JOIN RATINGS r ON r.naam = b.naam
                   AND r.fullname LIKE 'Obama'
    WHERE r.naam IS NULL

Performance


Of the three options, the NOT IN and LEFT JOIN/IS NULL perform equally. NOT EXISTS doesn't perform as well.

OMG Ponies
Nice summary of different methods. I'm adding a final extra one to my answer. RE performance: That's probably because the NOT EXISTS solution relies on a correlated subquery.
Roland Bouman
@Roland Bouman: All three produce different plans, but the EXISTS is 30% less efficient than the others - see the link.
OMG Ponies
Rolands solutions worked, but i couldnt read the result properly(see comment above).Im using your 'Not' solution now and im testing it as i type, because my query is more complex than the one i posted here.Thanks for the help. This is my first question here and im very satisfied!!
Checkerforth