Mysql объединяет запрос для нескольких «тегов» (отношение «многие ко многим»), которые соответствуют ВСЕМ тегам? - PullRequest
18 голосов
/ 16 июля 2010

Я пытаюсь запросить объекты, которые соответствуют ВСЕМ из данного набора тегов.

По сути, я хочу, чтобы пользователи могли добавлять все больше и больше тегов для фильтрации или «сужения» своих результатов поиска, как это делает 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, AND, объединившись:*

Но это не возвращает результатов, так как, когда результаты сгруппированы вместе, столбец OUTER JOINed Tags.name содержит только «tag1», а не «tag2».Строка результата, в которой найдено совпадение с тегом2, «скрывается» с помощью GROUPing.

Как мне сопоставить ВСЕ теги, чтобы получить эффект «сужения» или «детализации», который мне нужен?Благодаря.

1 Ответ

28 голосов
/ 16 июля 2010

Использование:

  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.

Нет необходимости в левом присоединении, если вам нужны только строки, в которых существуют оба тега.

...