Запрос 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.