У меня есть простой вопрос о наиболее эффективном способе выполнения определенного соединения.
Возьмите эти три таблицы, настоящие имена были изменены, чтобы защитить невиновных:
Таблица: животное
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
Я хочу найти всех животных, помеченных как "пушистые", "коричневые" и "милые". То есть животное должно быть помечено всеми тремя. На самом деле количество необходимых тегов может варьироваться, но это не имеет значения для данного обсуждения. Это запрос, который я придумал:
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), а план довольно обширен. Для такого «простого» запроса я обычно пытаюсь получить планы запросов с оценочной стоимостью, выраженной однозначным или двузначным числом.
Итак, мой вопрос: есть ли лучший способ выполнить этот запрос? Кажется, простой запрос, но я был в тупике, придумывая что-нибудь лучше.
AND
вместоOR
вWHERE tg.tag='fluffy' OR tg.tag='brown' OR tg.tag='cute'
- person John Woo   schedule 07.02.2012tag
не соответствует более чем одному значению, поэтому использование И не приведет к получению совпадающих строк. - person Branko Dimitrijevic   schedule 07.02.2012