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

MySQL实现基于多过滤器的搜索,mysql,sql,search,filtering,Mysql,Sql,Search,Filtering,从下面的表结构中,我希望能够提供基于属性组合的搜索过滤器: 表格:动物纪念品 id attributeId animalId 1 455 55 2 999 55 3 685 55 4 999 89 5 455 89 6 333 93 7 685

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

表格:动物纪念品

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
--------------------------------
attributeId    attributeCategoryId    attribute

233            1                      Fur
333            1                      Scales
455            1                      Feathers
685            2                      Black
999            2                      Brown
-----------------------------------------------
attributeCategoryId    category
1                      Body covering
2                      Colour
------------------------------------
前端会有复选框,例如

Animal options

Colour
[ ] Black      (id 685)
[x] Brown      (id 999)

Body Covering
[ ] Fur        (id 233)
[ ] Scales     (id 333)
[x] Feathers   (id 455)
我希望上面的复选框选择所有棕色和有羽毛的动物。我可以通过以下查询获取此数据:

SELECT animalId
FROM animalAttributes
WHERE attributeId IN (999,455)
GROUP BY animalId 
HAVING COUNT(DISTINCT attributeId) = 2;
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;
我遇到的问题是当从多个过滤器中选择多个选项时,例如

Animal options

Colour
[x] Black      (id 685)
[x] Brown      (id 999)

Body Covering
[x] Fur        (id 233)
[ ] Scales     (id 333)
[x] Feathers   (id 455)
我希望上面的复选框选择所有的动物(黑色棕色)有(毛发羽毛)。我可以通过以下查询获取此数据:

SELECT animalId
FROM animalAttributes
WHERE attributeId IN (999,455)
GROUP BY animalId 
HAVING COUNT(DISTINCT attributeId) = 2;
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”等,我是否正确地认为我需要计算所有组合()并遵循与上面相同的模式?e、 g.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;
其他参考表格

表格:属性

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
--------------------------------
attributeId    attributeCategoryId    attribute

233            1                      Fur
333            1                      Scales
455            1                      Feathers
685            2                      Black
999            2                      Brown
-----------------------------------------------
attributeCategoryId    category
1                      Body covering
2                      Colour
------------------------------------
表格:属性类别

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
--------------------------------
attributeId    attributeCategoryId    attribute

233            1                      Fur
333            1                      Scales
455            1                      Feathers
685            2                      Black
999            2                      Brown
-----------------------------------------------
attributeCategoryId    category
1                      Body covering
2                      Colour
------------------------------------
将与您所写的内容相同: 属性ID IN(68523345599233)

尝试:

或者说: (黑色或棕色和浅色)和(毛皮或羽毛和身体覆盖物)


取消测试,但您应该了解这一点。

您也可以通过交叉口执行此操作。您可以编写一个查询,为每个筛选器生成一个结果集。然后,您可以将所有结果集相交,得到一个适合所有过滤器的结果集


这种方法的缺点是在数据库上执行多个查询。如果性能是一个问题,因为你的应用程序有很多流量,你可以做一些内存密集型而不是进程密集型的事情,比如缓存你正在查询的数据库表,这样你只需要对数据库进行一次调用。

如果我正确理解你的问题,按位键可能会有所帮助。例如,假设每只动物都有多个二进制选项。例如has tail=是或否(0或1),has Scales、has Fir等的情况相同

然后,通过将所有可能的属性添加为一组二进制选项,您就可以

尾(Y/N)冷杉(Y/N)鳞片(Y/N)棕色(Y/N) 01101

也就是说,这种动物没有尾巴,有冷杉,没有鳞片,是棕色的


使用此键可以轻松筛选与该条件匹配的所有项目,并且可以添加新的条件,而无需对查询进行额外的代码更改。请查看使用这些键的按位运算符。

但一般来说,您是如何做到这一点的?如果您添加了另一个类别,那么您必须重写您的查询。必须有一个查询,允许在不更改查询的情况下添加新属性数据。如果您使用新房间扩建房屋,您将不得不在旧房子中建一扇门。
a.attributeCategoryId
不太可能同时是
1
2
。实际上,现在看起来您几乎成功了。您可能只需将'main'
,即,
WHERE(…)**和**(…)
,更改为
,并添加
HAVING COUNT(DISTINCT a.attributeCategoryId)=2
。拥有一些测试数据和预期的查询输出将非常有用,这样我们就可以尝试各种查询,直到得到正确的答案。