Выберите все идентификаторы в одной таблице, которые соответствуют как минимум столько же идентификаторов в другой таблице

0

Если у меня такая структура таблицы

[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.

  • 0
    Поделитесь тем, что вы пробовали.
Теги:

1 ответ

0

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;
  • 0
    В моих тестах этот запрос возвращает фильм, который имеет дополнительный жанр, которого нет в списке жанров пользователя. Я обновлю свой вопрос, чтобы показать что-то, что я пробовал (но мой тоже неверный).
  • 0
    Спасибо за обновления. Я на самом деле не хотел точных совпадений. Мне бы хотелось, чтобы набор жанров фильма был подмножеством набора пользовательских жанров. Так что фильм не должен иметь все жанры из пользовательских жанров, но не должен иметь те, которые не в пользовательских жанрах. Извините, если мне не ясно об этом. Тем не менее, кажется, что у меня работает некоторый код (проверьте мое обновление).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню