【问题标题】:Database Design: name-value pairs - good or bad?数据库设计:名称-值对——好还是坏?
【发布时间】:2011-05-17 19:03:24
【问题描述】:

假设我有一个在线商店,其中每个产品都分配有一个类别(并且有数百个类别可供选择)(例如“书籍”、“便携式 DVD 播放器”等)。如果我需要为每个类别提供描述性字段(例如,“作者”将是“书籍”类别的字段),那么在数据库中表示这一点的最佳方式是什么?

选项 1(名称值对):

===========================
 field
===========================
- field_id
- category_id (FK, referring to category like "book")
- name
- value

这意味着我可以依赖一个表来处理任何类别。我担心将这些数据与其他书籍并排显示所需的数据透视可能是一个潜在问题。

选项 2(单个表):

===========================
 book_field
===========================
- book_field_id
- book_id (FK, referring to the actual book)
- author
- title
- publisher
- date_published
...

这意味着我需要为每个类别创建一个表格。

注意:我认为这并不重要,但类别将来自类别层次结构(例如电子产品 -> DVD 播放器 -> 便携式 DVD 播放器)。

【问题讨论】:

    标签: mysql database database-design


    【解决方案1】:

    我的 0.02 美元 - 每个类别一张桌子。如果情况确实不同,那就接受它并相应地设置您的表格。

    当然,如果某些实体具有公共数据,则可以对其进行抽象/规范化,但我认为您那里的名称/值对选项可能会导致一些令人讨厌的可读性/查询性能问题。

    【讨论】:

    • 现实世界的笔记 - 在我的工作中,我们有几种非常相似但具有独特属性的表格 - 我们为每个表格使用特定的表格,一些常见元素(姓名,地址等)的表格。 ),以及一些在我们需要将这些对象作为一个整体查看时帮助我们聚合它们的视图。
    • 鲍勃所说的。另请搜索“泛化专业化关系建模”。
    • 同意。名称-值对系统很难返回一个简单的数据表,其中每个类别(BookID、作者、标题等)都有一列。
    • 您建议为每个类别创建一个表。如果您需要添加一个新类别,您是否必须为其创建一个新表?在生产中,我宁愿在现有表中添加一行而不是创建一个新表。在对象关系映射框架中事情变得很棘手,比如在 Rails 中。
    • 具有讽刺意味的是,我们现在正在做这件事(新医院形式)。添加新实体通常还包括滚动新的 UI 组件、构建新的 ORM 映射等,因此插入新表、新 UI 并连接好东西只是我们用户故事的一部分:)
    【解决方案2】:

    您确定要限制在一个类别中吗?我的意思是,您能想到您的产品可以属于多个类别的任何情况吗?

    好吧,无论如何,这里有一个可能对您有用的解决方案:

    更新(添加了几层)

    ========
    products
    ========
    - product_id
    - name
    
    ====================
    categories_products
    ====================
    - category_product_id
    - product_id (FK)
    - category_id (FK)
    
    ===========
    categories
    ===========
    - category_id
    - name
    
    =============================
    products_detail_values_types
    =============================
    - product_detail_value_type_id
    - product_id (FK)
    - detail_value_type_id (FK)
    
    ====================
    detail_values_types
    ====================
    - detail_value_type_id
    - detail_value_id (FK)
    - detail_type_id (FK)
    
    ===============
    detail_values
    ===============
    - detail_value_id
    - value
    
    =============
    detail_types
    =============
    - detail_type_id
    - name
    

    你有一个叫做“导演”的类型:

     detail_type:
       detail_type_id: 100
       name: "director"
    

    还有一些价值:

    detail_value:
      detail_value_id: 200
      value: "James Cameron"      
    

    类型和值的映射:

    detail_value_type:
      detail_value_type_id: 300
      detail_value_id: 200
      detail_type_id: 100
    

    哪些细节属于产品:

    product_detail_value_type:
      product_detail_value_type: 400
      product_id: 500
      detail_value_type_id: 300
    

    然后我们有类别:

    category:
      category_id: 600
      name: "movie"
    

    以及品类-产品映射:

    category_product:
      category_product_id: 700
      product_id: 500
      category_id: 600
    

    最后是产品本身:

    product:
      product_id: 500
      name: "Aliens"
    

    【讨论】:

    • @hade,现在你让我有点担心了。一个产品真的可以分为两个类别吗?我一直在研究亚马逊。不知道我是否见过这样的案例。我错了吗?
    • @hade,这种设计让我有可能拥有多个“詹姆斯卡梅隆”。这是标准化的吗?
    • @StackOverflowNewbie:假设您有电影类别。您可以拥有不同格式的电影:VHS、DVD、蓝光。您希望如何对它们进行分类?它们都是电影,但最好也根据媒体类型对它们进行分类。假设您要搜索蓝光格式的电影。您可以通过在电影类别和蓝光类别中搜索产品来轻松做到这一点。
    • 是的,在这个设计中你可以拥有多个“詹姆斯卡梅隆”。这是一个很简单的例子。其实电影可以有好几个导演,比如科恩兄弟。您实际上需要单独的人员表以及详细信息和人员表之间的多对多关系。我想知道这个答案在那之后是否很简单。
    • @hade,在您的示例中,也许“电影”是类别,而“蓝光”是一个细节(如其他细节:导演、流派等)。你怎么看?
    【解决方案3】:

    我建议您将您的设计建立在互联网标签所基于的基础上。

    让我解释一下:

    您的主要对象表还需要 4 个表。

    第一个:名称标签表,这是一个基本的表id |名称,将存储对象的属性:“作者”、“大小”、“重量”;任何可以描述物体的东西

    tag_table
    id    varchar(36)
    tag   varchar(36)
    

    第二个 :该表将把值与存储在 tag_table 值中的标签名称相匹配。它确实具有相同的设计

    value_table
    id    varchar(36)
    value varchar(36)
    

    第三个​​:将决定哪个值是哪个标签。

    tag_value
    id_pair  varchar(36)
    id_tag   varchar(36)
    id_value varchar(36)
    

    第四个:将一个对象与它的数据连接起来

    object_tag_value
    id_object  varchar(36)
    id_pair    varchar(36)
    

    最后是你的对象表。

    实现层次系统

    对于一对多或多对多层次结构,实现一个额外的表来关联这两个对象:

    object_relation
    id_parent varchar(36)
    id_son    varchar(36)
    

    对于多对一(例如带有 manager_id 的员工表),只需将 id_parent 添加为对象的成员。

    使用此架构,您将具有高度可扩展性,对象现在可以拥有无​​限特性,您不再受限制。另外,您可以避免数据冗余,因为标签名称是唯一的。

    希望我说的够清楚,对你有帮助,

    【讨论】:

    • 层次结构呢?您的解决方案中没有层次结构的概念,对吧?
    • 层次结构有两个概念,1 对多和多对多。如果您需要一对多,很容易在您的对象表中添加一个 parentId。如果是多对多添加表层次结构,其中包含两个 varchar(36) 字段,这将是另一个对象之间的关系,您可以通过这种方式拥有无限的层次结构。
    • 如果我只需要一对多的层次结构,我还应该采用您提出的解决方案吗?
    • 我修改了我的原始帖子,并写了一些关于层次结构的内容,是的,它适用于您的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    • 2010-11-12
    • 2011-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-30
    相关资源
    最近更新 更多