MySQL基于多个过滤器实现搜索

时间:2011-06-01 23:01:13

标签: mysql sql search filtering

从下面的表格结构中,我希望能够根据属性组合提供搜索过滤器:

表: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
------------------------------------

3 个答案:

答案 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

即这只动物没有尾巴,有冷杉,没有鳞片,是棕色的。

此键可以轻松过滤匹配该条件的所有项目,并且可以添加新条件,而不会对查询进行其他更改。查看按位运算符以使用这些键。

相关问题