Mysql объединяет запрос для нескольких "тегов" (отношения "многие ко многим" ), которые соответствуют всем тегам?
Я пытаюсь запросить объекты, которые соответствуют всем заданным наборам тегов.
В принципе, я хочу, чтобы пользователи могли добавлять все больше и больше тегов для фильтрации или "сужения" результатов поиска, вроде как newegg.com.
Моя структура таблицы - это таблица объектов, таблица тегов и таблица отношений MANY: MANY ObjectsTags. Поэтому у меня есть запрос JOIN:
SELECT * FROM Objects
LEFT OUTER JOIN ObjectsTags ON (Objects.id=ObjectsTags.object_id)
LEFT OUTER JOIN Tags ON (Tags.id=ObjectsTags.tag_id)
Я попытался использовать условие/условие IN, например:
SELECT * FROM Objects
LEFT OUTER JOIN ObjectsTags ON (Objects.id=ObjectsTags.object_id)
LEFT OUTER JOIN Tags ON (Tags.id=ObjectsTags.tag_id)
WHERE Tags.name IN ('tag1','tag2')
GROUP BY Objects.id
Но я узнал, что это имитирует серию OR, поэтому чем больше тегов вы добавляете к запросу, тем больше результатов вы получаете, вместо того, чтобы набор результатов суживался, как я надеялся.
Я также попытался выполнить несколько условий LIKE WHERE, ANDed вместе:
SELECT * FROM Objects
LEFT OUTER JOIN ObjectsTags ON (Objects.id=ObjectsTags.object_id)
LEFT OUTER JOIN Tags ON (Tags.id=ObjectsTags.tag_id)
WHERE Tags.name LIKE 'tag1'
AND Tags.name LIKE 'tag2'
GROUP BY Objects.id
Но это не возвращает никаких результатов, поскольку, когда результаты группируются вместе, столбец OUTER JOINed Tags.name содержит только "tag1", а не "tag2". Строка результата, где "tag2" соответствует "спрятан" GROUPing.
Как я могу сопоставить ВСЕ теги, чтобы получить эффект "узкий вниз" или "древовидный" эффект, который я получаю? Спасибо.
Ответы
Ответ 1
Использование:
SELECT *
FROM OBJECTS o
JOIN OBJECTSTAGS ot ON ot.object_id = o.id
JOIN TAGS t ON t.id = ot.tag_id
WHERE t.name IN ('tag1','tag2')
GROUP BY o.id
HAVING COUNT(DISTINCT t.name) = 2
Вам не хватало предложение HAVING.
Нет необходимости в LEFT JOIN, если вам нужны только строки, в которых есть оба тега.