Запрос MySQL из нескольких таблиц связанных между собой другими таблицами

Dm1tro

Есть 5 таблиц (так разбито из-за размера. Таблицы имеют units~15k, params~12k, units_params~60k записей):

units (id,name)
colors (id,name)
units_colors (unit_id,color_id)
params (id,name)
units_params (unit_id,param_id)

Каким образом оптимальнее производить поиск:

в названии юнита есть фраза: 'car'
есть цвет: 'black' и 'green'
нет цвета: 'red'
eсть параметр: 'wood'

На данный момент производится поиск сначала по имени. Список подходящих id скидывается в массив. После производится второй поиск по цвету в диапазоне id из массива. и т.д. Можно ли выполнить эту операцию одним MySQL запросом?

3 ответа

Dm1tro

select * from colors
where id in ( select units_colors.colors_id from units_colors, units where units_colors.unit_id= units.id and units.name like 'ваше значение'
);

и т.д.


Dm1tro

Точно по вашим условиям я бы написал как то так:

select * from units u where u.name like '%car%' and (2, 0)=(select sum(c.name in('black','green')), sum(c.name in('red')) from units_colors uc, colors c where c.id=uc.color_id and uc.unit_id=u.id) and exists(select 1 from units_params up, params p where up.param_id=p.id and p.name='wood' and up.unit_id=u.id)

Теоретически, если нужно какое то универсальное решение можно было бы остановиться на проверке всех условий тем способом как в этом запросе проверяются цвета и только подставлять параметры в суммы "должны быть" и "не должны быть" и меняя ожидаемые количества совпавших параметров в левой части равенства.


Dm1tro

Спасибо всем за ответы. Пришел к такой цепочке благодаря Ксении. До этого что я пытался делать, были проблемы с логикой запроса. Вариант Майка я пока не разобрал, он немного сложноват для меня.

SELECT * FROM units
WHERE name LIKE '%car%' AND id IN ( SELECT unit_id FROM units_params, params WHERE params.id=param_id AND params.name LIKE '%wood%'
) AND id IN ( SELECT unit_id FROM units_colors, colors WHERE colors.id=color_id AND colors.name = 'black'
) AND id IN ( SELECT unit_id FROM units_colors, colors WHERE colors.id=color_id AND colors.name = 'green'
) AND id NOT IN ( SELECT unit_id FROM units_colors, colors WHERE colors.id=color_id AND colors.name != 'red'
)

licensed under cc by-sa 3.0 with attribution.