4

我觉得这个问题可能已经被问了一千次了,所以如果它被回答了,我很抱歉。如果是这样,有人可以指出我正确的帖子/链接吗?

我想做的是为我的网站构建一个多面导航。它使用 MySQL,这是我正在使用的表的粗略草图:

产品:
- ID
- 标题
- 描述
属性:
- product_id
- 姓名
- 价值
类别:
- ID
- 姓名
products_to_categories:
- product_id
- category_id

我想要做的是在您处于某个类别时显示可用属性列表,允许您为每个属性选择一个或多个值。举个例子,看看 Office Depot 的这个页面:http ://www.officedepot.com/a/browse/binders/N=5+2177/

到目前为止,我已经使用了很多连接来过滤多个属性:

选择产品。*,a_options。*
FROM products_to_categories AS pc, products,
attributes AS a_options, /* 我可以继续完善的属性/值对列表 */
attributes AS a_select1 /* 第一个选择的属性 */
attributes AS a_select2 /* 第二个选择的属性 */
...
哪里 pc.category_id = 1
AND products.id = pc.product_id
和 a_options.product_id = products.id
AND a_options.name != '颜色' AND a_options.name != '尺寸'
和 a_select1.product_id = products.id
AND a_select1.name = '颜色' AND (a_select1.value = '蓝色' OR a_select1.value = '黑色')
和 a_select2.product_id = products.id
AND a_select2.name = '大小' AND a_select2.value = '8.5 x 11'

基本上a_options将返回那些产品的所有属性,这些产品是我使用a_select1和应用的过滤器的子集a_select2。因此,如果我使用 Office Depot 中的 Binders 示例,我想在为颜色选择蓝色或黑色并为尺寸选择“8.5 x 11”后显示所有可用属性。

然后我使用 PHP 代码删除重复项并将生成的属性排列到一个数组中,如下所示:

属性[name1] = (val1, val2, val3, ...)
属性[name2] = (val1, val2, val3, ...)

有没有办法可以加快查询速度或更有效地编写它?我在属性表(以及所有 ID 号)中设置了名称和值的索引。但是如果有人选择了几个属性,那么查询运行速度很慢。

提前感谢您的帮助,
Sridhar

4

2 回答 2

8

“然后我使用 PHP 代码删除重复项”

那时它不会扩展。

在我阅读http://www.amazon.com/Data-Warehouse-Toolkit-Techniques-Dimensional/dp/0471153370之后,我不停地推出方面和过滤机制。

基本思想是您使用星型模式..

您创建一个存储事实的事实表

customerid | dateregisteredid | datelastloginid
1 | 1 | 1
2 | 1 | 2

您在存储属性的维度表中使用外键

date_registered
Id | weekday | weeknumber | year | month | month_year | daymonth | daymonthyear
1 | Wed      | 2            | 2009 | 2   |2-2009      | 4        | 4-2-2009

然后无论您使用哪个日期“范式”,从该维度表中获取所有 id 并

 select * from the fact table where the fact.dateregisteredid is IN( ... the ids from the date dimension table that represent your time period)

您的数据的这些“索引视图”应该驻留在单独的数据库中,并且对生产中的对象的更改应该将该记录排队以便在分析系统中重新索引。大型网站可能会在非高峰时间将他们的记录批量发送到统计报告应用程序,但总是滞后几个小时或几天。如果架构支持,我总是尽量保持第二。

如果您正在显示行数预览,您可能还需要实现一些优化或缓存。

基本上总而言之,您复制数据并进行非规范化。该技术的名称为“数据仓库”或 OLAP(在线分析处理)。

有更好的方法,使用像甲骨文这样的商业数据库,但星型模式使得任何拥有开源关系数据库的人都可以使用它,并且有一段时间。

您绝对应该阅读该工具包,但他讨论了很多可以为您节省大量时间的事情。类似于处理更新数据的策略,以及在报告应用程序中保留审计历史记录。对于每个问题,他都概述了多种解决方案,每种解决方案都适用于不同的环境。

如果您不采取简单的方法并使用大量不必要的连接,它可以扩展到数百万行。

于 2009-12-02T07:26:37.000 回答
6

您可以根据规范化的数据库表生成分面表。
例如:

> SELECT * FROM product_facet
product_id | facet_type | facet_value
1          | color      | blue
2          | color      | blue
3          | color      | green
4          | color      | yellow
1          | speed      | slow
2          | speed      | slow

然后只需执行此查询即可获取每个属性的总数:

SELECT facet_type, facet_value, COUNT(facet_value) as total
FROM product_facet
GROUP BY facet_type, facet_value;

结果:

facet_type | facet_value | total
color      | blue        | 2
color      | green       | 1
color      | yellow      | 1
speed      | slow        | 2

使用条件搜索时,您可以通过匹配产品 id 选择构面表:

SELECT facet_type, facet_value, COUNT(facet_value) as total
FROM product_facet
WHERE product_id in (SELECT product_id FROM products WHERE ... )
GROUP BY facet_type, facet_value;
于 2014-01-28T05:02:32.583 回答