2015-10-07 3 views
1

У меня проблема с упрощенным запросом без необходимости создания запроса с PHP.MySQL несколько внутренних соединений против подзапроса

Моя проблема:

Продукт может иметь несколько свойств, например. цвет, размер и состояние. Чтобы получить продукт, который имеет все 3 свойства я могу:

products p 

INNER JOIN product_propeties p1 on p.pid = p1.pid AND p1.property = 1 (color) 

INNER JOIN product_propeties p2 on p.pid = p2.pid AND p2.property = 2 (size) 

INNER JOIN product_propeties p3 on p.pid = p3.pid AND p3.property = 3 (state) 

Это прекрасно работает. Я получу все продукты, у которых есть все эти 3 свойства.

Моя проблема в том, что я не хочу создавать p1, p2, p3 с PHP. Свойства перечислены в таблице «property_groups». В этой таблице я могу группировать свойства.

proberty|title|group_name 

1|color|winterspecial 

2|size|winterspecial 

3|state|winterspecial 

Хочу присоединиться к «property_groups» таблица «winterspecial» и мой пример из выше я не знаю, как. Проблема в том, что каждое свойство должно существовать. Несколько отдельных объединений выполняют эту работу. Но как это сделать в одном MySQL Query.

С PHP я выбрать все «winterspecial», а затем я построить запрос с p1, p2 ...

Там должно быть лучше. Помните, что свойства должны быть AND connectet. ИЛИ легко это будет простым подзапросом.

INNER JOIN product_propeties p1 on p.pid = p1.pid AND product_propeties IN (
    SELECT * FROM property_groups WHERE "winterspecial" 
) 
+0

Я не понимаю. Вы хотите показать продукт со всеми его свойствами? Вместо «игрушек», «зеленых», «15», «сломанных» вы хотите выбрать «игрушку», «цвет = зеленый», «размер = 15», «состояние = сломан»? Или что еще? Покажите желаемый результат. –

+0

Имейте в виду, что подзапрос и объединение - это то же самое, ни медленнее, ни быстрее. – Mjh

+0

@Mjh. , , Они функционально эквивалентны, но не обязательно реализуются одинаково. ОП. , , Пожалуйста, отредактируйте вопрос и укажите образцы данных и желаемые результаты. Полный запрос может также передать то, что вы пытаетесь сделать. –

ответ

0

Это может выглядеть немного неуклюжим, но это единственное, что я могу придумать на данный момент ...

Для того, чтобы узнать, есть ли продукт все winterspecial свойства, мы могли бы рассчитывать все существующие winterspecial свойства и winters свойства свойства продукта, а затем сравнить два числа.

Тогда мы можем выбрать один из продуктов и product_properties, где идентификатор продукта в найденном наборе:

select ... 
from products p 
join product_properties pp on pp.pid = p.pid and pp.property in 
    (select property from property_groups where group_name = 'winterspecial') 
where p.pid in 
(
    select pid 
    from product_properties 
    where property in 
    (select property from property_groups where group_name = 'winterspecial') 
    group by pid 
    having count(*) = 
    (select count(*) from property_groups where group_name = 'winterspecial') 
); 
0

Ааа, я думаю, что я получаю проблему сейчас. Кажется, вам нужны все продукты, которые имеют свойства в таблице property_groups, для данной группы.

Вот такой подход. Сделайте cross join, чтобы сгенерировать список продуктов и свойств. Затем сделайте left join в соответствии с product_properties. При агрегации, вы можете легко сказать, если все желаемые свойства соответствуют существующему свойству:

select p.* 
from products p cross join 
    property_groups g left join 
    product_properties pp 
    on pp.pid = p.id and pp.property = g.property 
where g.group_name = 'winterspecial' 
group by p.id 
having count(distinct pp.property) = count(distinct g.property) 

Вы можете на самом деле просто оговорка к одному из них having:

having sum(pp.property is null) = 0   -- no null values 
having count(pp.property) = count(g.property) -- all match 

Они все должны быть эквивалентны.

Смежные вопросы