SQL запрос для выбора через связь

Темы, не касающиеся фреймворка, но относящиеся к программированию в целом.
Ответить
Аватара пользователя
nihaha
Сообщения: 91
Зарегистрирован: 2017.02.12, 13:30

SQL запрос для выбора через связь

Сообщение nihaha » 2018.06.03, 01:25

Делаю фильтр товаров для ИМа. Есть таблица товаров, характеристик и таблица прикрученных к товару значений для фильтра (shop_values), не отдельные значения, а уже принадлежащие конкретному товару.

shop_products
===========
id
name


shop_characteristics
===========
id
values (json)


shop_values
===========
product_id
characteristic_id
value


С фронта получаю данные characteristic_id и value и могу выбрать все товары с этими параметрами через связь таким образом:

Код: Выделить всё

SELECT `p`.* FROM `shop_products` `p` 
LEFT JOIN `shop_values` `fv` ON `p`.`id` = `fv`.`product_id` 
WHERE ((`fv`.`characteristic_id`=3) AND (`fv`.`value`='уличные'))
Если в рамках группы характеристик (один и тот же characteristic_id) сделать множественный выбор на фронте, то тоже удается выполнить запрос и найти все товары, изменив условие

Код: Выделить всё

...
WHERE ((`fv`.`characteristic_id`=3) AND (`fv`.`value`='уличные')) 
OR ((`fv`.`characteristic_id`=3) AND (`fv`.`value`='внутренние'))
но если сделать множественный выбор между группами хар-к (разные characteristic_id), то найти ничего не удается, хотя товар имеет обе характеристики и оба значения привязаны в таблице shop_value

Код: Выделить всё

...
WHERE ((`fv`.`characteristic_id`=3) AND (`fv`.`value`='уличные')) 
AND ((`fv`.`characteristic_id`=5) AND (`fv`.`value`='белый'))
Судя по всему, сделать так не получается, потому что связи записаны двумя отдельными строками в БД.
Вопрос как правильно написать SQL-запрос или же как тогда спроектировать хранение связей?
Важный момент - условие между группами хар-к должно быть AND, а не OR, иначе множественный выбор будет выбирать все подряд.

Аватара пользователя
ElisDN
Сообщения: 4984
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: SQL запрос для выбора через связь

Сообщение ElisDN » 2018.06.03, 10:47

Код: Выделить всё

LEFT JOIN `shop_values` `fv1` ON `p`.`id` = `fv1`.`product_id`
LEFT JOIN `shop_values` `fv2` ON `p`.`id` = `fv2`.`product_id`
...
WHERE ((`fv1`.`characteristic_id`=3) AND (`fv1`.`value`='уличные'))
AND ((`fv2`.`characteristic_id`=5) AND (`fv2`.`value`='красные'))
...

Аватара пользователя
nihaha
Сообщения: 91
Зарегистрирован: 2017.02.12, 13:30

Re: SQL запрос для выбора через связь

Сообщение nihaha » 2018.06.03, 11:42

Да, так работает, спасибо.
На стаке подсказали еще такой вариант

Код: Выделить всё

SELECT `p`.* FROM `shop_products` `p`
LEFT JOIN `shop_values` `fv` ON `p`.`id` = `fv`.`product_id`
WHERE ((`fv`.`characteristic_id`=2) AND (`fv`.`value`='Foscam'))
OR ((`fv`.`characteristic_id`=3) AND (`fv`.`value`='внутренние'))
GROUP BY `p`.`id` HAVING COUNT(*)=2;

Ответить