Проблема выбора SQL из многих в многие таблицы

0

У меня есть две связанные таблицы, которые для этого вопроса будут называться posts и tags. posts содержит различные сообщения, например, найденные в системе форума сообщества. tags содержит уникальный набор тегов, которые добавляются, когда сервер обнаруживает новый тег, который еще не находится в системе. В каждом теге есть только одна запись.

posts может иметь несколько тегов, а tags может иметь более одного сообщения, которое является ссылкой на него. Чтобы обрабатывать эти ссылки взад и вперед, я создал таблицу для размещения между этими двумя таблицами, называемую posttags. posttags содержит ссылку на id tag и id post. Так поддерживаются отношения многих и многих.

Теперь, к проблеме. Мне нужно иметь возможность выбирать сообщения на основе тега. Это простое соединение, когда есть только один тег для поиска, но я не понимаю, как обрабатывать несколько тегов. Например, мне нужно иметь возможность искать базу данных и получать результаты, содержащие ВСЕ теги, которые находятся в списке (например, "php, mysql, sql" ), без использования SQL внутри цикла или любой другой низкой производительности варианты.

Я не уверен, как это сделать. Может ли кто-нибудь указать мне правильное направление?

Спасибо!

Теги:

2 ответа

3
Лучший ответ

Вы можете использовать следующий подход, 3 - количество запрошенных тегов.

SELECT PostId
FROM posttags pt, tags t
WHERE p.Id = pt.PostId
  AND t.Id = pt.TagId
  AND tagname In ('php', 'mysql', 'sql')
group by PostId
having count(*) = 3

или вы можете отсортировать запрошенные теги, присоедините их по порядку и используйте следующее:

Select * from Posts p,
(  
 SELECT PostId, GROUP_CONCAT(tagname ORDER BY tag_name DESC SEPARATOR ' ') Tags
 FROM posttags pt, tags t
 WHERE p.Id = pt.PostId
   AND t.Id = pt.TagId
 GROUP BY PostId

) t  WHERE t.PostId = p.Id    И t.Tags = 'mysql php sql'

Но вам нужно отсортировать теги

  • 0
    Круто, это работает! Спасибо.
1

Если вы хотите выбрать сообщения, которые имеют все теги в заданном наборе, вы можете использовать стратегию "подсчета":

SELECT
  p.*
FROM tags t
LEFT JOIN posttags pt
  ON pt.tag_id = t.tag_id
LEFT JOIN posts p
  ON p.post_id = pt.post_id
WHERE
  tags.tag IN ('php', 'mysql', 'sql')
GROUP BY p.post_id
HAVING COUNT(tags.tag_id) = 3;

Конечно, если вы измените набор, число "3" должно быть изменено на количество элементов в наборе.

  • 0
    Отличный ответ. И вы, и Майкл ответили на один и тот же вопрос, поэтому я должен был дать правильный ответ Майклу, так как он ответил первым. Тем не менее, спасибо за объяснение, что сделал запрос!

Ещё вопросы

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