Фильтрация записей с определённым тегом

Рейтинг: 1Ответов: 1Опубликовано: 27.03.2015

Есть 3 таблицы: новости posts - (id,postTitle,...), теги для новостей tags - (id,postId,tagName) и связи для тегов relTags - (id,postId,tagId).

Задача: не выводить новости с определённым тегом (тегами). Для этой цели есть таблица IgnoreTags - (id,userId,tagId).

Текущее решение в лоб: в условии вывода новостей добавляем такое -

 "AND ( SELECT count(id) FROM relTags
 WHERE p.id = postId AND tagId IN (
 игнорируемые теги через запятую )
  ) = 0"

Предварительно формируем "игнорируемые теги" из таблицы IgnoreTags для пользователя (например, если пользователь игнорирует теги с id 1 и 2, то будет так - "1,2"). Подключать таблицу связей relTags (через LEFT JOIN) и отбрасывать, так я тоже пытался, приходится использовать DISTINCT, и тогда всё работает ещё дольше.

Что делать? Как ускорить выполнение? Потому что в текущем варианте это работает ну очень долго (секунд по 5-7 минимум). Построение списка игнорируемых тегов через запятую выполняется очень быстро, а вот поиск необходимых новостей ужасно долго.

Я уже спрашивал подобное, но ответа не получил и всё это время пробовал всевозможные варианты: Хранение тегов в БД и работа с ними

Ответы

▲ 1

Попробуйте избавиться от агрегатных функций в условии, например:

AND posts.id NOT IN (SELECT postid from relTags rt
Where rt.tagid in (список игнорируемых тегов)
and rt.post_id = posts.id)

Или:

AND posts.id NOT IN (SELECT postid from relTags rt
join IgnoreTags on IgnoreTags.tagid = rt.tagid
Where IgnoreTags.userid = @user_id and rt.post_id = posts.id)