У меня простой вопрос о наиболее эффективном способе выполнения определенного объединения.
Возьмите эти три таблицы, настоящие имена были изменены, чтобы защитить невинных:
Таблица: животное
animal_id name ...
======================
1 bunny
2 bear
3 cat
4 mouse
Таблица: теги
tag_id tag
==================
1 fluffy
2 brown
3 cute
4 small
Таблица сопоставления: animal_tag
animal_id tag_id
==================
1 1
1 2
1 3
2 2
3 4
4 2
Я хочу найти всех животных, помеченных как ' пушистый ', ' коричневый ' и ' cute '. То есть животное должно быть помечено всеми тремя . В действительности количество требуемых тегов может варьироваться, но оно не должно иметь значения для этого обсуждения. Вот запрос, который я придумал:
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 - это DB), оценочная стоимость оптимизатора довольно высока (9945,12), а план довольно обширен. Для такого «простого» запроса я обычно пытаюсь получить планы запросов с ориентировочной стоимостью в одну или две цифры.
Итак, мой вопрос: есть ли лучший способ выполнить этот запрос? Похоже на простой запрос, но я был в тупике, придумывая что-то лучше.