从下面的表格结构中,我希望能够根据属性组合提供搜索过滤器:
表: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
--------------------------------
前端会有复选框,例如
Animal options
Colour
[ ] Black (id 685)
[x] Brown (id 999)
Body Covering
[ ] Fur (id 233)
[ ] Scales (id 333)
[x] Feathers (id 455)
我希望上面的复选框选择棕色 AND 的所有动物都有羽毛。我可以使用以下查询获取此数据:
SELECT animalId
FROM animalAttributes
WHERE attributeId IN (999,455)
GROUP BY animalId
HAVING COUNT(DISTINCT attributeId) = 2;
我遇到的问题是从多个过滤器中选择了多个选项,例如
Animal options
Colour
[x] Black (id 685)
[x] Brown (id 999)
Body Covering
[x] Fur (id 233)
[ ] Scales (id 333)
[x] Feathers (id 455)
我希望上面的复选框选择所有动物(黑色 OR 棕色) AND 具有(毛发 OR 羽毛) 。我可以使用以下查询获取此数据:
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;
如果我想添加其他过滤器,例如“Has Tail”,“Can fly”,“Blood type”等,我是否正确地认为我需要计算所有组合(cartesian product)和遵循与上面相同的模式?例如5个过滤器,每个过滤器都选择了1个或多个选项
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;
其他参考表
表:属性
attributeId attributeCategoryId attribute
233 1 Fur
333 1 Scales
455 1 Feathers
685 2 Black
999 2 Brown
-----------------------------------------------
表:attributeCategories
attributeCategoryId category
1 Body covering
2 Colour
------------------------------------
答案 0 :(得分:1)
attributeId IN (685,233) ||
attributeId IN (685,455) ||
attributeId IN (999,233) ||
attributeId IN (999,455)
与你写的一样: attributeId IN(685,233,455,999,233)
尝试:
SELECT aa.animalId
FROM animalAttributes aa
LEFT JOIN attributes a ON a.attributeId = aa.attributeId
WHERE
(aa.attributeId IN (685,99) AND a.attributeCategoryId=1) AND
(aa.attributeId IN (223,455) AND a.attributeCAtegoryId=2)
GROUP BY animalId
或者说: (黑色或棕色AND isColor)AND(毛皮OR羽毛AND isBodyCovering)
Untestet,但你应该明白这一点。
答案 1 :(得分:1)
你也可以用十字路口做到这一点。您可以编写一个查询,为每个过滤器生成结果集。然后,您可以将所有结果集相交,以得出适合所有过滤器的单个结果集。
这种方法的缺点是您正在对数据库进行多次查询。如果性能是一个问题,因为你的应用程序有很多流量,你可以做一些内存密集但不是进程密集的事情,比如缓存你正在查询的数据库表,这样你只需要调用一次数据库。
答案 2 :(得分:0)
如果我正确理解您的问题,按位键可能会有所帮助。例如,假设每只动物可以有多个二元选项。例如,tail = Yes或No(0或1),Has Scales,Have Fir等相同。
然后通过将所有可能的属性添加为二进制选项集,您可以使用此
尾(Y / N)冷杉(Y / N)刻度(Y / N)棕色(Y / N) 0 1 0 1
即这只动物没有尾巴,有冷杉,没有鳞片,是棕色的。
此键可以轻松过滤匹配该条件的所有项目,并且可以添加新条件,而不会对查询进行其他更改。查看按位运算符以使用这些键。