У меня есть две связанные таблицы, которые для этого вопроса будут называться posts
и tags
. posts
содержит различные сообщения, например, найденные в системе форума сообщества. tags
содержит уникальный набор тегов, которые добавляются, когда сервер обнаруживает новый тег, который еще не находится в системе. В каждом теге есть только одна запись.
posts
может иметь несколько тегов, а tags
может иметь более одного сообщения, которое является ссылкой на него. Чтобы обрабатывать эти ссылки взад и вперед, я создал таблицу для размещения между этими двумя таблицами, называемую posttags
. posttags
содержит ссылку на id tag
и id post
. Так поддерживаются отношения многих и многих.
Теперь, к проблеме. Мне нужно иметь возможность выбирать сообщения на основе тега. Это простое соединение, когда есть только один тег для поиска, но я не понимаю, как обрабатывать несколько тегов. Например, мне нужно иметь возможность искать базу данных и получать результаты, содержащие ВСЕ теги, которые находятся в списке (например, "php, mysql, sql" ), без использования SQL внутри цикла или любой другой низкой производительности варианты.
Я не уверен, как это сделать. Может ли кто-нибудь указать мне правильное направление?
Спасибо!
Вы можете использовать следующий подход, 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'
Но вам нужно отсортировать теги
Если вы хотите выбрать сообщения, которые имеют все теги в заданном наборе, вы можете использовать стратегию "подсчета":
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" должно быть изменено на количество элементов в наборе.