#sql #postgresql
#sql #postgresql
Вопрос:
Из-за скуки я решил настроить простую систему тегов для своих фильмов сегодня. У меня в основном есть список названий фильмов и X количество тегов для каждого фильма. База данных выглядит следующим образом:
mydb=# select id, title from movies;
id | title
---- ----------------------------------------
1 | first_movie
2 | second_movie
mydb=# select id, movie_id, tag_id from movie_tags;
id | movie_id | tag_id
---- ---------- --------
1 | 1 | 716
2 | 1 | 787
3 | 1 | 322
4 | 2 | 716
5 | 2 | 787
6 | 2 | 323
mydb=# SELECT l.id, l.title, t.tag_id FROM movies l, movie_tags t WHERE t.movie_id = l.id AND t.tag_id IN(716, 787, 323);
id | title | tag_id
---- -------------- --------
2 | second_movie | 787
2 | second_movie | 716
2 | second_movie | 323
1 | first_movie | 716
1 | first_movie | 787
Это третий запрос, который вызывает у меня проблемы. Во-первых, он показывает повторяющиеся строки. Новая строка для каждого tag_id
. Я этого не хочу. Я бы предпочел, чтобы для каждого фильма отображалась одна строка, соответствующая указанным тегам.
Что приводит меня ко второй проблеме. Как вы можете видеть, first_movie
не помечен tag_id=323
. Однако это все еще отображается в результатах.
Как я могу не показывать повторяющиеся строки и отфильтровать результаты по фильмам, которые соответствуют всем заданным тегам?
Я планировал создать для этого простой пользовательский интерфейс, поэтому надеялся на хороший «динамический» запрос, в который я могу поместить список tag_ids.
Ответ №1:
Этот запрос выдает вам все фильмы, в которых были найдены все 3 тега.
SELECT l.id, l.title
FROM movies l, movie_tags t
WHERE t.movie_id = l.id
AND t.tag_id IN (716, 787, 323)
GROUP BY l.id, l.title
HAVING COUNT(*) = 3
Как вы можете видеть, столбец тегов удален, потому что нет смысла включать один произвольный тег.
Ответ №2:
SELECT l.id, l.title
FROM movies l
WHERE l.id IN (SELECT t.movie_id
FROM movie_tags t
WHERE t.tag_id IN (716, 787, 323));