Reputation: 2189
SELECT * from movies
INNER JOIN movie_genres ON movies.id_movie=movie_genres.fk_id_movie
INNER JOIN genres ON movie_genres.fk_id_genre=genres.id_genre
WHERE genre_name IN ('action','crime');
movie_genres has just 2 columns (FK): - fk_id_movie - fk_id_genre
[movies]--------[movies_genres]-------[genres]
This returns an OR result: any movie which genre is 'action' OR 'crime';
Is it possible to write this with an AND result. Return only movies that have the 2 genres altogether?
Upvotes: 1
Views: 111
Reputation: 77876
SELECT * from movies
where id in
(
select movie_id from
movie_genres group by genre having count(genre) = 3
)
Upvotes: 0
Reputation: 4622
You should only select the columns you need, not all of them (*) unless you really need every single column of both tables in your results. It's better for performance.
SELECT movies.col1, movies.col2
FROM `movies`
INNER JOIN `movie_genres` ON movies.id = movie_genres.id_movie
GROUP BY movies.id
HAVING SUM( DISTINCT movie_genres.genre ) = 6
Upvotes: 0
Reputation: 26784
SELECT * from movies INNER JOIN movie_genres
ON movies.id=id_movie WHERE genre IN ('1','2','3')
GROUP BY movies.id
HAVING COUNT(DISTINCT genre)= 3;
Upvotes: 1
Reputation: 311308
What your query does is to join a single line of movies
with a single row of movie_genres
and then evaluate it - which, as you suggested, is not the result you're expecting.
Instead, you need to build some query which joins movies
with some aggregation of movie_genres
.
Gordon's answer is a great example of this. A different approach, assuming the combination of id_movie
and genre
is unique, is to count how many of the genres your movie matches:
SELECT *
FROM movies
INNER JOIN (SELECT id_movie, COUNT(*) AS matches
FROM movie_genres
WHERE genre IN ('1', '2', '3')
GROUP BY id_movie) genres ON movies.id=id_movie
WHERE matches = 3
Upvotes: 1
Reputation: 92
Yes, just use the AND keyword...
SELECT * from movies INNER JOIN movie_genres ON movies.id=id_movie WHERE (genre = 1 AND genre = 2 AND genre = 3);
Upvotes: 1
Reputation: 1269763
Yes. A good way to do this is with aggregation and a having
clause:
SELECT *
from movies INNER JOIN
movie_genres
ON movies.id=id_movie
GROUP BY movies.id
HAVING sum(genre = '1') > 0 and
sum(genre = '2') > 0 and
sum(genre = '3') > 0;
Upvotes: 2