Я рассмотрел множество вопросов по этой проблеме здесь, в Stackoverflow, но я думаю, что это не так.
То, что я пытаюсь сделать, это дать пользователю возможность фильтровать сообщения по тегам, чтобы можно было видеть только те теги, которые остались для фильтрации. Другими словами, если пользователь выбирает тег «tag1», он отображает сообщения с этим тегом, а также показывает другие теги, которые публикуют общие записи, но скрывают теги, которых после фильтрации не было видно.
У меня есть таблицы записей , posts_tags и теги . У posts_tags есть post_id и tag_id. Мне удалось получить post_ids с определенным набором тегов:
SELECT pt.post_id
FROM posts_tags pt
INNER JOIN tags t
ON pt.tag_id = t.id
WHERE t.name IN ('tag1', 'tag2', 'tag3')
GROUP BY pt.post_id
HAVING COUNT(DISTINCT t.id) = 3;
Допустим, этот запрос дает post_ids 1, 2, 3:
post 1 has tag1, tag2, tag3 and tag4
post 2 has tag1, tag2, tag3 and tag5
post 3 has tag1, tag2, tag3 and tag6
Теперь моя проблема заключается в , как расширить запрос так, чтобы он возвращал пользователю только tag4, tag5 и tag6 , поскольку эти теги по-прежнему доступны для дальнейшей фильтрации сообщений. Как этого добиться?
Было бы неплохо обратить внимание на производительность. У меня 130000 постов, 6500 тегов, а в бридж-таблице 240000 строк.
редактировать: использовать сценарий:
- Пользователь отправляет теги с автозаполнением и выбирает несколько тегов.
- Пользователь получает сообщения на основе отправленных тегов.
Пользователь ищет больше тегов и в этот момент:
Я не хочу давать полный список, а только те, которые
а. Это еще не было выбрано.
б. Используются в сообщениях, которые были получены на шаге 2.

РЕДАКТИРОВАТЬ: ЗАКЛЮЧИТЕЛЬНЫЙ ЗАПРОС НА ОСНОВЕ ОТВЕТА Мости Мостачо:
SELECT DISTINCT pt2.tag_id, t2.name FROM
(SELECT pt1.post_id
FROM posts_tags pt1
INNER JOIN tags t1
ON pt1.tag_id = t1.id
WHERE t1.name in ('tag1','tag2','tag3')
GROUP BY pt1.post_id
HAVING COUNT(DISTINCT t1.id) = 3) MatchingPosts
INNER JOIN posts_tags pt2 ON (MatchingPosts.post_id = pt2.post_id)
INNER JOIN tags t2 ON (pt2.tag_id = t2.id)
WHERE t2.name NOT IN ('tag1','tag2','tag3');