I'm pulling a list of items from one table, on the basis of their being included in another table, like this:
select fruit.id, fruit.name from fruit, fruit_rating where fruit_rating.fruit_id=fruit.id group by fruit.name;
That works fine -- it basically produces a list of all the fruit that has been rated by someone. But now, I want to exclude all fruit that has been rated by one specific user, so I tried this:
select fruit.id, fruit.name from fruit, fruit_rating where fruit_rating.fruit_id=fruit.id and fruit_rating.user_id != 10 group by fruit.name;
That's ok, but not quite right. It shows all the fruit that have been rated by people other than 10, but if users 1 and 10 have both rated the same fruit, it still shows that one. Can anyone tell me how to construct a query that shows only the fruit that have NOT Been rated by user 10, regardless of who else has rated them?
One thing that isn't quite 100% clear to me: do you want all fruit that hasn't been rated by user 10, or just fruit that has been rated by other people but not by user 10? e.g. should fruit that has no ratings be included?
I think you want all fruit (including unrated), in which case Noah and Mr. Brownstone's answers aren't quite what you're after. If you remove the inner join to fruit_rating, and the now-needless group by, theirs will include unrated fruit. An alternative approach, which avoids the subselect, is
That is, do a left join (an optional join, if you like) onto fruit rating ONLY for user 10, and then only return rows where a match WASN'T found.
I read this differently from Cowan, and agree with Noah...
Find all fruit where: - User 10 did not rate it - Atleast one other user did rate it
However, in my experience using NOT IN can be quite slow. So, I generally prefer to filter using LEFT JOIN in the same way as Cowan. Here are a few different options, though I have not had time to test performance on large data sets...
As this only works for one user, I would also consider making a table of "users to exclude" and LEFT JOIN on that instead...
Or something much more long winded, but I suspect is the fastest on larger data sets with appropriate indexes...
I refined your query a bit to make it a little easier to read, and added a subquery to filter out all of the fruit that's been rated by user 10