Если у меня такая структура таблицы
[movies]---<[movies_genres]>---[genres]---<[users_genres]>---[users]
Я хотел бы запросить, учитывая user.id
, только фильмы, которые делятся своим жанром с users_genres.genre_id
.
Чтобы быть более четким, если пользователю нравятся жанры {sci-fi, action и romance}, но фильм {sci-fi, action и horror}, фильм не должен возвращаться. Однако, если фильм просто {sci-fi} или {sci-fi, action}, он должен быть возвращен. Поэтому, если у него есть жанр, не указанный в предпочтительных для пользователя жанрах, его не нужно возвращать.
Как мне это сделать?
Благодарю.
Редактировать:
Что-то я пробовал
select movies_id from movies_genres mg
where mg.genres_id not in (
select genres_id from users_genres ug
where ug.users_id = 1
)
Edit2:
Хорошо, я исправил вышеуказанный код, и я думаю, что он работает
select * from movies
where movies.id not in (
select movies_id from movies_genres mg
where mg.genres_id not in (
select genres_id from users_genres ug
where ug.users_id = 2
)
)
Я в основном играю с вычитающими наборами (я думаю). Для меня это совсем не так, поэтому я даже не понимаю, как работает SQL. Только это, если я могу вычесть один набор из другого, и в итоге он становится пустым, это подмножество. Это в основном соответствует моим требованиям movie_genres, являющимся подмножеством users_genres.
join
и aggregation
должно работать между таблицами:
select mg.movie_id
from user_genres ug left join
movie_genres mg
on mg.genre_id = ug.genre_id
where ug.user_id = ?
group by mg.movie_id
having count(*) = count(ug.genre_id); -- do all match
РЕДАКТИРОВАТЬ:
Если вы хотите только точные совпадения, то простой способ - создать список жанров и совпадение по этому поводу:
select mg.movie_id
from (select mg.movie_id, group_concat(mg.genre_id order by mg.genre_id) as genres
from movie_genres mg
group by mg.movie_id
) mg join
(select group_concat(ug.genre_id order by ug.genre_id) as genres
from user_genres ug
where ug.user_id = ?
) ug
on mg.genres = ug.genres;