В отношении HABTM, как найти элементы, которые должны соответствовать более чем одному критерию в соответствующей таблице - PullRequest
1 голос
/ 16 февраля 2011

Надеюсь, кто-то понял название ...

Допустим, у меня есть следующее отношение, теги животных HABTM.

таблица животных

id  name
1   dog
2   whale
3   Elephant

таблица тегов:

id  name
1   brown
2   gray
3   terrestrial
4   aquatic

таблица ссылок

animal_id   tag_id
1           1
1           3
2           2
2           4
3           2
3           3

Я хотел бы получить всех животных, у которых есть Tag = серый И Tag = водный

Это легко, только с одним критерием

SELECT * FROM `animals` as a 
left join animals_tags at on a.id = at.animal_id
Where at.tag_id = (select id from tags where name = 'brown')

Можно ли сделать один запрос для более чем одного тега?Или я должен получить результаты для каждого тега, а затем извлечь пересекающиеся результаты?

Ответы [ 2 ]

2 голосов
/ 16 февраля 2011

Примечание. Я использую идентификаторы тегов вместо имен тегов.

Если вы хотите выбрать 1 строку на животное:

SELECT a.*, GROUP_CONCAT(t.name) tags
FROM `animals` as a 
  LEFT JOIN animals_tags at ona.id = at.animal_id
  LEFT JOIN tags t ON at.tag_id = t.id
GROUP BY a.id
HAVING SUM(at.tag_id = 1) > 0 AND SUM(at.tag_id = 4) > 0

Если вы также хотите получить все теги для каждого животного:

SELECT a.*, t.*
FROM animals a JOIN ( 
    SELECT animal_id
    FROM animals_tags
    GROUP BY animal_id
    HAVING SUM(tag_id = 1) > 0 AND SUM(tag_id = 4) > 0
  ) ag ON a.id = ag.animal_id
  LEFT JOIN animals_tags at ON a.id = at.animal_id
  LEFT JOIN tags t ON at.tag_id = t.id
1 голос
/ 16 февраля 2011

INTERSECT было бы неплохо, если бы MySQL имел его, но вы могли бы выполнить это с помощью предложения HAVING, теоретически.

SELECT a.name FROM `animals` as a 
left join animals_tags at ona.id = at.animal_id
Where at.tag_id = (select id from tags where name = 'brown')
OR at.tag_id = (select id from tags where name = 'terrestrial')
GROUP BY a.name
HAVING COUNT(a.name) = 2
...