Reputation: 508
I'm trying to add the possibility to add multiple filters when fetching products from a database that has a basic entity-attribute-value model. The filters are based on attribute values like:
I have no problems with a single filter, but I don't know how to approach multiple filters at once.
EXAMPLE DATA: (reduced version)
SQL file with this example structure & data
Table products:
id name
1 jacket
2 shirt
Table product_variants:
id product_id
1 1
2 2
3 2
Table attributes:
id name
1 colors
2 sizes
Table attribute_value:
id attribute_id value
1 1 green
2 1 red
3 2 small
4 2 large
Table variant_details:
id product_variant_id attribute_value_id
1 1 3 (jacket - small)
2 2 1 (shirt - green)
3 2 3 (shirt - small)
4 3 1 (shirt - green)
5 3 4 (shirt - large)
For this example, the three variants would be:
THE GOAL:
I want to pass the ids for the attribute values and get the products matching ALL said attribute values, for example:
products.php?attr=1&4
Should fetch products that are green(1) AND large(4), for the example only the third variant matches the criteria, so the desired result would be:
product_id product_desc
2 shirt
WHAT I'VE TRIED:
I don't think it'll be much help but I have this for a single attribute:
products.php?attr=1
Should yield anything that has the attribute value green (1):
SELECT products.id, products.desc, attribute_value.value FROM products
LEFT JOIN product_variants ON products.id = product_variants.product_id
LEFT JOIN variant_details ON variant_details.product_variant_id = product_variants.id
LEFT JOIN attribute_value ON attribute_value.id = variant_details.attribute_value_id
WHERE attribute_value.id = 1
GROUP BY products.id
The problem with this is, before the WHERE clause, this is what it produces:
id name value
1 jacket small
2 shirt green
2 shirt small
2 shirt green
2 shirt large
and I don't know how to filter those rows that have the value column both green & large, for example. I'm thinking the approach I'm taking for the query is wrong.
Any help would be appreciated.
Upvotes: 2
Views: 799
Reputation: 508
I was able to get it working in a way with the following query:
SELECT products.id, products.desc FROM products
WHERE EXISTS
(
SELECT * FROM product_variants
LEFT JOIN variant_details ON variant_details.product_variant_id = product_variants.id
LEFT JOIN attribute_value ON attribute_value.id = variant_details.attribute_value_id
WHERE product_variants.product_id = products.id AND attribute_value.id = 1
)
AND EXISTS
(
SELECT * FROM product_variants
LEFT JOIN variant_details ON variant_details.product_variant_id = product_variants.id
LEFT JOIN attribute_value ON attribute_value.id = variant_details.attribute_value_id
WHERE product_variants.product_id = products.id AND attribute_value.id = 4
)
I say in a way because it will return all products that have every requested attribute in one or more of its variants.
Example:
Take a single product, a shirt that comes in two colors and two sizes, its variants could be:
Notice the absence of a red & large variant. If I do the above query with red & large it would still match this product because one of its variants has 'red' and another has 'large'.
I decided to add this as an answer instead of an edit because it accomplishes the goal of matching a product with two (or more) attributes but I'd still like to see an answer where the result is restricted to match a single variant of the product, or perhaps another way to achieve this.
Upvotes: 2