Database design 多级项目

Database design 多级项目,database-design,database-schema,Database Design,Database Schema,我们正在尝试构建一个应用程序来描述我们的价目表。价目表本身是多层次的,因此一个项目的价格取决于许多“选项”。我想在这里举个例子是我最好的选择 目前我有以下表格: 项目: 项目ID(主键) 名称 主要选项: 主选项ID(主键) 名称 子选项: 子选项ID(主键) 主选项ID(FK) 名称 项目至子项目选项 项目ID 子选项ID 这是我们目前拥有的结构–以下是一个示例,以演示其工作原理: 物品:沙发 主选项:长度 子选项:40“-50” 项目至子项目选项:沙发的项目标识,40“-50”子项目标识 你

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

目前我有以下表格:

项目:

项目ID(主键)
  • 名称
  • 主要选项:

    主选项ID(主键)
  • 名称
  • 子选项:

    子选项ID(主键)
  • 主选项ID(FK)
  • 名称
  • 项目至子项目选项

    • 项目ID
    • 子选项ID
    这是我们目前拥有的结构–以下是一个示例,以演示其工作原理:

    物品:沙发

    主选项:长度

    子选项:40“-50”

    项目至子项目选项:沙发的项目标识,40“-50”子项目标识

    你明白了。到现在为止,一切都很简单。它基本上允许每个项目有无限量的子选项和主选项

    现在,我们试图实现的是对所描述的解决方案的深入了解,或者是一个多级选项解决方案

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

    物品:沙发

    主选项:形状

    子选项:1/2圆

    “1/2圆”需要有一个额外的主_选项-“直径”将有子_选项(50”圆、60”圆等)。这些选项与项目没有直接关系,但与之前在上层选择的子选项“1/2圈”有关联


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

    我可以考虑两种方法来设计类似的内容。但首先要认识到的是,您的数据在结构上具有固有的层次性,不一定非常规则。这意味着使用传统的关系数据库并不特别适合这种类型的数据。然而,这是可以做到的

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

    
    Item {
       main_options: [{
          name: "Shape",
          sub_options: [{
              name: "1/2 Circle",
              //  Other fields here
          }]
       },
       {
          //  Other main option
       }]
    }
    
    这种基于文档的数据模型的优点在于,您不必遵循固定的模式。如果一个项目需要几个嵌套的选项集,您只需直接用这种方式定义该项目的文档即可。尽管每个“item”文档可能有很大的不同,但它们都存储在同一个“集合”中,您可以执行查询以查找不同的项。例如,您可以要求数据库查找带有“1/2圆”子选项“形状”的所有项目

    如果您习惯于使用关系数据库,那么转向MongoDB之类的东西会有点让人心神不定,但我认为在这种情况下,它实际上非常适合您的数据性质

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

    
    item (id (pk), name: text, ...)
    
    option (id (pk), owner: option_id (fk), name: text, ...)
    
    item_options (item_id, option_id)
    
    因此,这里我们定义了我们的item表和另一个表,该表将一个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'; 
    
    正如您所看到的,项目结构越深,您必须进行越多的联接来查询层次结构中的深层内容。这个查询只针对只有main和sub选项的对象


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

    您之所以难以做到这一点,是因为您对问题的思考有点错误。您不需要考虑包含子选项和其他子选项的主选项,而是要考虑由其他主选项组成的主选项

    如果您将主选项视为“特性”或“质量”,而将子选项视为“值”,那么这一点就更清楚了。在您的示例中,沙发具有“形状”属性。出于您的目的,形状可以是线性或圆形。线性形状具有长度特性,而圆形具有角度特性。这些品质都没有任何值:形状、线性、圆形。但是,这些质量:长度、角度确实有值。长度的值可能是40“-50”,角度的值可能是1/2圆

    因此,您的数据模型不需要太多更改:

    只需将另一个FK from MAIN_选项添加到自身。你会注意到这也是David提出的,除了David认为这是一个糟糕的第二选择,而实际上这是一个不错的第一选择


    您的规则是层次化的,RDBMS对于层次化数据来说可能很难使用,除非您深入研究层次结构。当您深入研究时,每个步骤都很简单。

    让我们假设我必须使用关系数据库——这不是更好的结构吗?还有其他人有不同的想法吗?没有更好的结构了。这是一个典型的关系数据库建模问题。Google提供了建模零件和子零件关系的示例