Выберите продукты по нескольким атрибутам, используя AND вместо ИЛИ concatenator, Модель данных EAV

У меня возникла проблема с запросом фильтра товаров на веб-сайте eCommerce.

У меня есть модель данных EAV, как это:

products          [id, title....]
attributes        [id, name]
attributes_entity [product_id, attribute_id, value_id]
attributes_values [id, value]

Мой запрос:

SELECT
products.id,
products.title
FROM
products
WHERE products.id IN
(
SELECT attributes_entity.product_id FROM attributes_entity INNER JOIN
attributes ON attributes_entity.attribute_id=attributes.id INNER JOIN
attributes_values ON attributes_entity.value_id=attributes_values.id
WHERE
(
(attributes.name="Memory" AND attributes_values.value="16GB")
>> AND
(attributes.name="Color" AND attributes_values.value="Gold")
)
)
AND products.category_id = :category_id

Проблема в том, что когда я использую >> AND между (attribute.name = «Memory» AND attribute_values.value = «16GB») подзапросами, я получаю 0 результатов, но когда я использую OR, это дает мне больше результатов, которые мне нужны, которые не актуально для этого 2 условия.

Например, когда я получаю запрос: «Память = 16 ГБ и Цвет = Черный». Я ожидаю получить iPhone 5 16BG Black, не все (золото, космический серый и т. Д.) IPhone с 16GB

Я ищу пример запроса, желательно с описанием того, как он работает.

С Уважением,
Антон

3

Решение

Ваш подзапрос должен быть таким:

SELECT
attributes_entity.product_id
FROM
attributes_entity INNER JOIN attributes
ON attributes_entity.attribute_id=attributes.id
INNER JOIN attributes_values ON
attributes_entity.value_id=attributes_values.id
WHERE
(attributes.name="Memory" AND attributes_values.value="16GB")
OR
(attributes.name="Color" AND attributes_values.value="Gold")
GROUP BY
attributes_entity.product_id
HAVING
COUNT(DISTINCT attributes.name)=2

Это решение использует подзапрос GROUP BY. Вы должны использовать ИЛИ, потому что атрибут не может быть одновременно «Память» и «Цвет» в одной строке, они могут быть истинными, но в разных строках. COUNT (DISTINCT attribute.name) подсчитывает числовые атрибуты либо Color, либо Memory, если их 2, то есть хотя бы 1 строка, где первое условие истинно, и 1 строка, где другое также верно.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]