У меня есть структура БД, которая предназначена для хранения атрибутов для конкретных объектов в легко расширяемом виде.
Существует таблица «Объекты».
+----+----------------------
| id | ....(name, type, etc)
+----+----------------------
Далее у меня естьТаблица «Атрибуты».
+----+------+
| id | Name |
+----+------+
И, наконец, таблица «Отношения», используемая для хранения всех данных в виде пар атрибут-объект (в качестве первичного ключа) с соответствующими значениями.
+--------+---------+-------+
| id_obj | id_attr | value |
+--------+---------+-------+
Мне нужно получить идентификаторы для объектов, которые удовлетворяют нескольким условиям одновременно.Например, у меня есть атрибуты с именами «Тип» и «Город», и мне нужно выбрать идентификаторы для объектов, где соответствующие значения для этих атрибутов - «Квартира» и «Город b».
Лучшее решениеМне удалось придумать после того, как со вчерашнего дня ударился головой о стену (ну, единственное, что хорошо в этом запросе, - это то, что он действительно работает и выбирает необходимые записи):объем хранимых данных может потенциально стать несколько большим, и я боюсь, что все эти подзапросы (может потребоваться указать около 10-15 фильтров), каждый из которых анализирует всю БД, могут вызвать серьезные проблемы с производительностью (не говоря уже о том, чтодаже с моими ограниченными навыками SQL я уверен, что должен быть лучший способ сделать то, что мне нужно).
С другой стороны, радикальные изменения в БД на самом деле не вариант, так как код, работающий сэто сильно зависит от текущей структуры БД.
Есть ли способ проверить атрибуты так, как мне нужно, в грехеgle запрос, с ограниченным количеством или без изменений в структуре хранимых данных?
Рабочий запрос, эквивалентный приведенному выше, но гораздо лучше оптимизированный, кредитует DRapp :
SELECT STRAIGHT_JOIN
rel.id_obj
from
relations rel
join attributes atr
on rel.id_attr = atr.id
where
( rel.value = 'Apartment' AND atr.name = 'Type' )
or ( rel.value = 'City b' AND atr.name = 'City' )
group by
rel.id_obj
having
count(*) = 2
limit
0, 20