Question

Given three tables like this:

fruit:          taste:        fruit_taste:
id  name        id  name      id  fruit_id  taste_id
--  ----        --  ----      --  --------  --------
1   apple       1   sweet     1   1         1
2   lime        2   tart      2   1         2
3   banana                    3   2         2
4   lemon                     4   4         2

How can I SELECT only the fruit which do have not been identified by the join table as having a sweet taste? My desired results should also include 'banana', since there is not a fruit_taste identifying it as sweet.

I tried (along with a ton of other things):

SELECT * 
FROM fruit
LEFT OUTER JOIN fruit_taste
ON fruit_taste.fruit_id = fruit.id
WHERE (fruit_taste.taste_id != 1 OR fruit_taste.id IS null)

which almost works, but still gives me 'apple' in my result, since my apple is a Granny Smith, and is both sweet and tart. How can I exclude 'apple' in my query? Is my only option a subquery with NOT IN?

Was it helpful?

Solution 3

You can use a LEFT JOIN and avoid the subquery if you add the excluded taste to the JOIN filter and then exclude matching rows. This should generally be better for performance than using NOT IN on a subquery, but YMMV.

SELECT *
FROM fruit
LEFT JOIN fruit_taste 
  ON fruit_taste.fruit_id = fruit.id
  AND fruit_taste.taste_id = 1
WHERE fruit_taste.id IS NULL

OTHER TIPS

select *
from fruit
where id not in
(select ft.fruit_id
from fruit_taste ft
inner join taste t
on ft.taste_id = t.id
where t.name = 'sweet')

Aside from using NOT IN, you can also use LEFT JOIN. To filter out fruits that have no sweet taste, the total number of sweet for every fruit should be 0.

SELECT  a.ID, a.Name
FROM    fruit a
        LEFT JOIN fruit_taste b
            ON a.id = b.fruit_id
        LEFT JOIN taste c
            ON b.taste_id  = c.id
GROUP   BY a.ID, a.Name
HAVING  SUM(IFNULL(c.name = 'sweet', 0)) = 0
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top