У меня есть простой вопрос о наиболее эффективном способе выполнения определенного соединения.
Возьмем три таблицы, реальные имена изменены для защиты невинных:
Таблица: animal
animal_id name ... ====================== 1 bunny 2 bear 3 cat 4 mouse
Таблица: tags
tag_id tag ================== 1 fluffy 2 brown 3 cute 4 small
Mapping Table: animal_tag
animal_id tag_id ================== 1 1 1 2 1 3 2 2 3 4 4 2
Я хочу найти всех животных, которые помечены как 'пушистые', 'коричневые' и 'милые'. То есть животное должно быть помечено всеми тремя. В реальности количество необходимых меток может варьироваться, но для данного обсуждения это не имеет значения. Вот запрос, который я придумал:
SELECT * FROM animal
JOIN (
SELECT at.animal_id FROM animal_tag at
WHERE at.tag_id IN (
SELECT tg.tag_id FROM tag tg
WHERE tg.tag='fluffy' OR tg.tag='brown' OR tg.tag='cute'
)
GROUP BY at.animal_id HAVING COUNT(at.tag_id)=3
) AS jt
ON animal.animal_id=jt.animal_id
На таблице с тысячами "животных" и сотнями "меток" этот запрос работает достаточно быстро... 10 десятков миллисекунд. Однако, когда я смотрю на план запроса (в качестве БД используется Apache Derby), расчетная стоимость оптимизатора довольно высока (9945.12), а план довольно обширен. Для такого "простого" запроса я обычно стараюсь получить план запроса с оценочной стоимостью в одно- или двузначных числах.
Поэтому мой вопрос заключается в том, есть ли лучший способ выполнить этот запрос? Кажется, что это простой запрос, но я не смог придумать ничего лучше.