From the table structure below I'd like to be able to provide search filters based on combinations of attributes:
Table: animalAttributes
id attributeId animalId
1 455 55
2 999 55
3 685 55
4 999 89
5 455 89
6 333 93
7 685 93
8 999 93
--------------------------------
The front end would have checkboxes e.g.
Animal options
Colour
[ ] Black (id 685)
[x] Brown (id 999)
Body Covering
[ ] Fur (id 233)
[ ] Scales (id 333)
[x] Feathers (id 455)
I'd expect the above checked boxes to select all animals that are brown AND have feathers. I can get this data with the following query:
SELECT animalId
FROM animalAttributes
WHERE attributeId IN (999,455)
GROUP BY animalId
HAVING COUNT(DISTINCT attributeId) = 2;
The issue I'm having is when there are multiple options selected from multiple filters e.g.
Animal options
Colour
[x] Black (id 685)
[x] Brown (id 999)
Body Covering
[x] Fur (id 233)
[ ] Scales (id 333)
[x] Feathers (id 455)
I'd expect the above checked boxes to select all animals that are (black OR brown) AND have (fur OR feathers). I can get this data with the following query:
SELECT animalId
FROM animalAttributes
WHERE
attributeId IN (685,233) ||
attributeId IN (685,455) ||
attributeId IN (999,233) ||
attributeId IN (999,455)
GROUP BY animalId
HAVING COUNT(DISTINCT attributeId) = 2;
If I wanted to add additional filters such as "Has Tail", "Can fly", "Blood type", etc, am I right in thinking I'd need to calculate all combinations (cartesian product) and follow the same pattern as above? e.g. 5 filters, each with 1 or more options selected
attributeId IN (x,x,x,x,x) ||
attributeId IN (x,x,x,x,x) ||
attributeId IN (x,x,x,x,x) ||
...
HAVING COUNT(DISTINCT attributeId) = 5;
other tables for reference
Table: attributes
attributeId attributeCategoryId attribute
233 1 Fur
333 1 Scales
455 1 Feathers
685 2 Black
999 2 Brown
-----------------------------------------------
Table: attributeCategories
attributeCategoryId category
1 Body covering
2 Colour
------------------------------------