我有一些产品属于同一类别。
每个类别可以拥有不同的属性。
例如,
- 类别汽车具有属性颜色、功率等。
- 类别宠物具有属性体重、年龄等。
类别数量约为10-15个。 每个类别中的属性数量为3-15。 产品数量非常大。
此应用程序的主要需求是非常好的搜索功能。我们将选择类别,并输入此类别中每个属性的条件。
必须为这种情况设计数据库。(SQL Server 2005)
我有一些产品属于同一类别。
每个类别可以拥有不同的属性。
例如,
类别数量约为10-15个。 每个类别中的属性数量为3-15。 产品数量非常大。
此应用程序的主要需求是非常好的搜索功能。我们将选择类别,并输入此类别中每个属性的条件。
必须为这种情况设计数据库。(SQL Server 2005)
传统的设计方法如下(星号表示主键列):
Product
ProductId*
CategoryId: FK to Category.CategroyId
Name
Category
CategoryId*
Name
Property
PropertyId*
Name
Type
CategoryProperty
CategoryId*: FK to Category.CategoryId
PropertyId*: FK to Property.PropertyId
ProductProperty
ProductId*: FK to Product.ProductId
PropertyId*: FK to Property.PropertyId
ValueAsString
如果您可以接受每个属性值都将作为字符串传递到数据库,并且类型转换信息存储在 Property 表中的事实,那么这种布局就足够了。
查询大致如下:
SELECT
Product.ProductId,
Product.Name AS ProductName,
Category.CategoryId,
Category.Name AS CategoryName,
Property.PropertyId,
Property.Name AS PropertyName,
Property.Type AS PropertyType,
ProductProperty.ValueAsString
FROM
Product
INNER JOIN Category ON Category.CategoryId = Product.CategoryId
INENR JOIN CategoryProperty ON CategoryProperty.CategoryId = Category.CategoryId
INNER JOIN Property ON Property.PropertyId = CategoryProperty.PropertyId
INNER JOIN ProductProperty ON ProductProperty.PropertyId = Property.PropertyId
AND ProductProperty.ProductId = Product.ProductId
WHERE
Product.ProductId = 1
提供更多的WHERE条件(使用AND连接),查询速度会更快,但前提是你已经对表进行了正确的索引。
然而,在全文索引的情况下,这种解决方案并不理想。可以通过另外一张表以一种更非规范化的方式存储与ProductId相关联的所有文本来解决这个问题。这个表需要通过监听ProductProperty表中的变化触发器来更新。
tProduct
productID
<other product details>
tCategory
categoryID
<other category details>
tProperty
propertyID
<other property details>
tProductXCategory
productyID
categoryID
tCategoryXProperty
categoryID
propertyID
您的查询将需要使用映射表连接数据,但这将允许您在类别、属性和产品之间拥有不同的多对多关系。
使用存储过程或参数化查询来提高搜索性能。
你可以尝试一些更面向对象的方法。
Products(ProductID, CategoryID, <任何其他共同属性>)
Categories(CategoryID, Name, Description, ..)
从这里开始,你有很多选择,几乎所有的选择都会破坏数据库的规范化。
如果需要添加新产品,将成为维护噩梦。
Cars(CarID, ProductID, ..)
Pets(PetID, ProductID, ..)
SELECT <fields> FROM Cars INNER JOIN Products ON Cars.ProductID = Products.ProductID
对于不同类型的属性(即 int、varchar 等),将成为维护噩梦。
CategoryProperty (CPID, Name, Type)
PropertyAssociation (CPID, PropertyID)
Properties(CategoryID, PropertyID, Name, Type)
PropertyValueInt(ProductID, CPID, PropertyID, Value)
- 用于 int 类型
PropertyValueString(ProductID, CPID, PropertyID, Value)
- 用于字符串类型
PropertyValueMoney(ProductID, CPID, PropertyID, Value)
- 用于货币类型
通过使用这种方法,您不必在单独的表格中管理所有属性,而是管理它们的值类型。基本上,涉及的所有表都将是查找表。 缺点是,为了检索每个值,您必须为每个值类型进行“Case”操作。
在选择这些方法中,请参考这些文章(这里和这里)。即使它是关于本地化的,这篇论坛帖子也很有趣并与主题相关。我最近不得不这样做,我正在使用NHibernate,其中有三个实体
Product Category Option OptionCategory
一个产品有1 *的类别
一个产品有1 *的选项
一个选项有1个OptionCategory
一旦这个设置完成,您就可以使用Nhibernate缓存
谢谢