Как отфильтровать несколько значений с несколькими JOIN - PullRequest
2 голосов
/ 17 декабря 2010

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

Рассмотрите следующие 4 таблицы:

products : id (int), имя, msrp и т. д. *

субпродукты : id (int), product_id (int), name (varchar)

subproducts_properties : id (int), subproduct_id (int), property_id (int)

subproducts_properties_values ​​: subproducts_properties_id (int), значение (varchar)

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

Теперь представьте, что существует продукту этого есть многократные субпродукты, у которых есть много свойств, у которых есть многократные значения.В частности, этот продукт имеет субпродукт, который имеет следующие свойства:

Свойство 1 - property_id: 1;значение = '.17 HMR';

Свойство 2 - property_id: 22;value = 'Bolt';

Где property_id 1 имеет имя Caliber, а property_id 2 имеет имя Action (думаю: оружие).

Что это за продукт not have - это подпродукт, содержащий свойство с property_id=1 и value='5.56 mm NATO'.

. У пользователя есть раскрывающиеся списки, в которых он может выбрать несколько наборов фильтров на основе уникальных значений.Поэтому, если пользователь выбирает Caliber из .17 HMR и Action из Bolt, он должен ожидать увидеть наш продукт, но когда он откатится назад Bolt и Caliber, скажем, 5.56 mm NATO он должен видеть нет продуктов, потому что наш продукт не соответствует обоим фильтрам.

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

SELECT p.*, m.name as manufacturer_name, pt.name as product_type_name, COUNT(DISTINCT com.id) AS num_reviews, ROUND(AVG(com.rating), 1) as rating, pi.image_thumb 
FROM products p 
        LEFT JOIN manufacturers m ON p.manufacturer_id=m.id 
        LEFT JOIN product_types pt ON p.product_type_id=pt.id 
        LEFT JOIN comments com ON p.id=com.object_id AND com.object_group = 'com_products' AND com.level=0 
        LEFT JOIN ( 
                SELECT product_id, thumb_path as image_thumb 
                FROM products_images pi 
                ORDER BY ordering ASC 
            ) AS pi ON p.id=pi.product_id 
        LEFT JOIN subproducts sp ON p.id=sp.product_id 
        LEFT JOIN subproducts_properties spp ON sp.id=spp.subproduct_id 
        LEFT JOIN subproducts_properties_values sppv ON spp.id=sppv.sp_id 
WHERE p.deleted != 1 AND p.published=1 
            AND ( 
                        IF(spp.property_id=1, IF(sppv.value='5.56 mm NATO',1,0), 0) = 1 
                    OR IF(spp.property_id=22, IF(sppv.value='Bolt',1,0), 0) = 1
                ) 
GROUP BY p.id 
ORDER BY p.created DESC 
LIMIT 0, 12

Часть, на которой нужно сосредоточиться, является последней AND в предложении WHERE, где я пытаюсь запустить фильтры.Также обратите внимание, что у меня есть GROUP BY, чтобы иметь возможность выполнять агрегатные функции в других таблицах.Этот конкретный запрос отзовет наш продукт из-за OR внутри этого последнего AND, но я бы хотел настроить его так, чтобы в этом случае он не откатывался назад, а откатывался назад, если вместо sppv.value='5.56 mm NATO' есть sppv.value='.17 HMR' (это значение для нашего субпродукта).

Я попытался вместо этого вставить AND, но он ничего не возвращает, потому что у каждого значения есть собственная строка вsppv table.

Пожалуйста, помогите!Я полностью потерян для того, что делать здесь.

Заранее спасибо!

1 Ответ

1 голос
/ 17 декабря 2010

попробуйте Имеющий - Счет - Если вместо где:

WHERE p.deleted != 1 AND p.published=1 
GROUP BY p.id 
HAVING COUNT(IF(spp.property_id = 1 AND sppv.value='5.56 mm NATO',1,NULL)) > 0 
       AND COUNT(IF(spp.property_id=22 AND sppv.value='Bolt',1,NULL)) > 0
ORDER BY p.created DESC
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...