多级项目

时间:2011-12-21 19:53:30

标签: database-design database-schema

我们正在尝试构建一个描述我们价目表的应用程序。价格表本身是多层次的,因此物品的价格取决于许多“选项”。我想一个例子是我最好的选择。

目前我有以下表格:

档案:

  • Item_ID(PK)
  • 名称

Main_Option:

  • Main_Option_ID(PK)
  • 名称

Sub_Option:

  • Sub_Option_ID(PK)
  • Main_Option_ID(FK)
  • 姓名

Item_To_Sub_Option

  • Item_ID
  • Sub_Option_ID

这是我们目前拥有的结构 - 这是一个展示其工作原理的示例:

项目:沙发

Main_Option:长度

Sub_Option:40“-50”

Item_To_Sub_Option:沙发的Item_ID,40“-50”Sub_Option_ID

你得到了照片。直到这里,它非常直接。它基本上允许每个项目具有无限量的子选项和主要选项。

现在,我们要努力实现的是深入了解所描述的解决方案或多级选项解决方案。

例如,一个更复杂的项目,我需要生成更多选项,但这些选项不是从项目生成 - 而是从其他子选项生成。示例如下:

项目:沙发

Main_Option:Shape

Sub_Option:1/2 Circle

“1/2圈”需要有一个额外的Main_Option - “Diameter”,它将具有Sub_Options(50“Round,60”Round等)。这些选项与项目没有直接关系,而是与之前在上一级选择的子选项“1/2 Circle”相关。

设计数据库以实现此解决方案的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

你正在努力解决这个问题的原因是你正在以一种错误的方式思考这个问题。您可以根据由其他主要选项组成的主要选项来考虑它,而不是考虑具有其他子选项的子选项的主要选项。

如果您将主要选项视为“特征”或“品质”,将子选项视为“值”,那么这会变得更加清晰。在您的示例中,沙发的质量为“SHAPE”。出于您的目的,SHAPE可能是LINEAR或ROUND。线性形状具有LENGTH的质量,而圆形具有ANGLE的质量。这些品质都没有任何:SHAPE,LINEAR,ROUND。然而,这些品质:LENGTH,ANGLE确实有价值。 LENGTH的值可能是 40“-50”,而ANGLE可能是 1/2 Circle

因此,您的数据模型无需进行太多更改:

ERD

只需将MAIN_OPTION中的另一个FK添加到自身。你会注意到这也是大卫提出的,除了大卫认为这是一个糟糕的第二选择,而实际上这是一个很好的首选。

您的规则是分层的,RDBMS对于分层数据可能很尴尬,除非您在层次结构中向下钻取。当您向下钻取时,每个步骤都很简单。

答案 1 :(得分:0)

我可以通过两种方式来设计这样的设计。首先要认识到的是,您的数据在结构上具有固有的层次结构,并不一定非常规律。这意味着使用传统的关系数据库不太适合这种类型的数据。但是,它可以做到。

我自己可能使用的第一种方法是选择一个非关系数据库,例如MongoDB,它用于存储“文档”的集合。文档本质上有点像Object,并且可以在其中包含其他嵌入文档。这对于您的数据类型尤其有用。您可以创建这样的数据模型:


Item {
   main_options: [{
      name: "Shape",
      sub_options: [{
          name: "1/2 Circle",
          //  Other fields here
      }]
   },
   {
      //  Other main option
   }]
}

这种基于文档的数据模型的优点在于您必须遵守 no 固定架构。如果一个项目需要多个嵌套的选项集,那么您就可以直接前进并以这种方式定义该项目的文档。尽管每个“项目”文档可能完全不同,但它们都存储在相同的“集合”中,您可以执行查询以查找不同的项目。因此,您可以要求数据库查找所有带有“1/2”圆形选项“形状”的项目。例如。

如果您习惯使用关系数据库,那么转移到像MongoDB这样的东西是一种思维转变,但我认为在这种情况下它实际上很适合您数据的性质。

另一方面,如果你绝对必须使用关系数据库,那么你需要将事物建模为层次结构,这可能会有点棘手。基本上你需要有点像你已经描述过的表格,虽然我已经用我在这里做的改变重申了它们:


item (id (pk), name: text, ...)

option (id (pk), owner: option_id (fk), name: text, ...)

item_options (item_id, option_id)

所以这里我们定义了item表和另一个表,它将一个项映射到它的一组主选项,这些选项在“option”表中定义。

选项表包含一个额外字段“owner”,对于主选项,您将设置为“null”,但对于子选项,您将此字段设置为主选项的选项ID,或者可能是“拥有”它的子选项。使用这种结构,您可以将选项嵌套到您喜欢的任何深度。以下是一些示例数据:


item (1, "Sofa", ...)
option (1, null, "Shape", ...)
option (2, null, "Length", ...)
option (3, 1, "1/2 Circle", ...)
option (4, 1, "3/4 Circle", ...)
option (5, 2, "Short", ...)
option (6, 2, "Long", ...)
option (7, 5, "Specific Short Measurement", ...)
option (8, 5, "Other Short Measurement", ...)
item_options (1, 1)
item_options (1, 2)

将关系数据库用于此类数据的缺点是查找内容的查询并不容易。例如,要使用“1/2圆圈”选项搜索所有沙发,您可能需要以下内容:


select * from item i inner join item_options io on i.id = io.item_id inner join option o on io.option_id = o.id left join option o2 on o.id = o2.owner where o.name = 'Shape' and o2.name = '1/2 Circle'; 

正如您所看到的,项目结构越深,您在查询层次结构深层内容时所需的连接就越多。而且该查询只适用于只有主要和子选项的东西。

无论如何,我希望这能为你提供一些如何建模的选择。

相关问题