一尘不染

您如何建模实体的自定义属性?

sql

假设我们有一个应该能够存储所有产品的应用程序。每个产品至少具有anID和a,Name但其他所有属性都可以由用户自己定义。

  1. 例如,他可以创建一个产品组 Ipod ,其中将包含 容量世代 属性 __
  2. 例如,他可以创建一个具有 大小颜色 属性的产品组 TShirts
  3. 我们需要存储产品的定义和具体产品本身。
  4. 我们希望确保可以轻松地按产品属性进行汇总(GROUP BY)。例如,选择每一代ipod的总容量
  5. 该解决方案必须不需要架构更改(由于Bill Karwin的输入而增加了要求-也请参见他的答案!)

您将如何根据上述要求对架构进行建模?

注意: 要求4.很重要!

感谢大家的贡献和讨论方法。我过去曾见过一些解决此问题的方法,但是没有一个对我来说容易分组:(


阅读 132

收藏
2021-03-17

共1个答案

一尘不染

分组将变得不容易,因为您要在“颜色”上使用什么聚合运算符?请注意,案例2不能使用您的要求4。

无论如何,仅由于数据类型的差异而很难进行汇总,并且可以通过以更加类型安全的方式进行处理来减轻聚合-知道添加苹果和橙子绝对没有道理。

这是经典的EAV模型,在经过精心设计的数据库中占有一席之地。为了使它更具有类型安全性,我已经看到了将值存储在类型安全表中而不是单个自由格式varchar列中的情况。

代替值:

EntityID int
,AttributeID int
,Value varchar(255)

您有多个表:

EntityID int
,AttributeID int
,ValueMoney money

EntityID int
,AttributeID int
,ValueInt int

etc.

然后获取每一代的iPod容量:

SELECT vG.ValueVarChar AS Generation, SUM(vC.ValueDecimal) AS TotalCapacity
FROM Products AS p
INNER JOIN Attributes AS aG
    ON aG.AttributeName = 'generation'
INNER JOIN ValueVarChar AS vG
    ON vG.EntityID = p.ProductID
    AND vG.AttributeID = aG.AttributeID
INNER JOIN Attributes AS aC
    ON aC.AttributeName = 'capacity'
INNER JOIN ValueDecimal AS vC
    ON vC.EntityID = p.ProductID
    AND vC.AttributeID = aC.AttributeID
GROUP BY vG.ValueVarChar
2021-03-17