Извлечение постов по нескольким тегам

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

Дано: в БД типа mySQL есть 3 таблицы (перечислю только поля, имеющие отношение к вопросу):

  1. post (id)
  2. tag (id, text)
  3. tagpost (id, tagid, postid)

Таблица tag содержит описание тега (слово и его идентификатор). При добавлении тега на пост, помещается запись в таблицу tagpost с идом тега и поста. В таблицу tagpost добавляется столько записей, сколько было добавлено тегов на этот пост.

Нужно: Юзер в интерфейсе указал выборку по двум тегам. Нужно извлечь посты, которые помечены и тегом1 и тегом2. Извлечь посты, помеченные только одним определенным тегом - не составляет труда (inner join), но как красиво решить задачу при нескольких тегах? Пусть не за 1 запрос, но чтобы в итоге быстро работало. А то на ум приходит только говнокод. ps. Метку "php" в вопросе поставил, т.к. кодится на этом языке, вдруг понадобятся специфичные функции из него.

Ответы

▲ 3Принят

Самое простое - приджойнить теги два раза, сначала один, потом второй:

select p.* from post p 
    join tagpost tp1 on tp1.post=p.id join tag t1 on tp1.tag=t1.id 
    join tagpost tp2 on tp2.post=p.id join tag t2 on tp2.tag=t2.id 
    where t1.name='tag1' and t2.name='tag2';

Но для неизвестного количества тегов такой запрос без квери билдера строить будет неудобно и некрасиво. Более акуратный вариант:

select p.* from tagpost tp join tag t on tag=t.id 
    join post p on post = p.id where name in ('tag1','tag2') 
    group by post having count(1) = 2;

но здесь надо помнить, что запросы с group by сложнее в оптимизации.