数据库设计:同时考虑共享和扩展的父/子;独特的孩子

时间:2012-01-18 22:11:16

标签: database-design parent-child classification

[已更新]:请参阅下面的答案。

我可能不会很好地解释这一点,但无论如何我都会给它一个旋转,因为这一直在破坏我的想法:

目标的简单解释:我想设计一个父/子关系,从父母开始,将允许一个组/子组有一个或多个:

  1. a sub_group,
  2. 一个没有子女的唯一群组项目,或
  3. 对项目的共享列表的引用(见下文)。
  4. 我遇到的墙:我知道我可以在一个包含parent_id列的单个表中建立基本的父/子关系,但问题是很多我的父/子组将共享一些相同的信息(“list”),并且一式两份地输入和维护这些子项/组将变得非常乏味。我希望拥有的内容最好通过以下图表和解释来描述:

    Groups |  Shared Lists   |  Unique Lists
    -------|-----------------|--------------
    Studs  |                 |  StudType
         \ |                 | /
           > Widths > Gauges >
         / |                 | \
    Track  |                 |  TrackType
    

    解释如果没有意义则发表评论):

    • 我有两个规范的父母StudsTrack
    • 我有四个列表WidthsGaugesStudTypeTrackType
    • BOTH StudTrack共享相同的Widths列表。
    • Widths中的
    • 每个项目共享相同的Gauges列表。
    • Gauges组引用的Studs中的
    • 每个项将引用 StudType列表。
    • Gauges组引用的Track中的
    • 每个项将引用 TrackType列表。

    (注意:我意识到我可以开始具体并在向下钻取时转移到共享列表(即Studs> StudType> Widths> {{1 }}),但为了这个目的,我想假设上面的解释/图表是如何完成的。)

    我的问题 [已更新] 这是否是考虑重复输入问题的正确方法?我是在正确的轨道上还是离开基地?有没有人对我应该如何实现/重新考虑这个有什么建议? 假设设计是正确的,如果可行的话,我可以一次引用一个组合,即使它们基本上只存在于一个组合中虚拟关系?我非常感谢任何帮助/方向与我的情况。

2 个答案:

答案 0 :(得分:1)

以下所有内容都是我的意见,但这是一个很好的做法:好的,它终于让我了解了你所得到的。是的,库存,零件清单或您试图跟踪的任何物品集合中可能有一个OO(即亲子)角色:每个item都有一个标尺,有 - 一个等级,有一个宽度,有一个材料,有一个打孔/没有打孔,有一个长度,有一个完成,等等任何项目的可能属性列表,包括螺柱,轨道,#2松木板,一块板岩。等等。你想要建立的亲子关系优雅而简洁。

但是如果你打算在数据库表中明确地尝试表达这种父子关系,你就会遇到麻烦,你最终会很快重新设计数据库。但可以在数据库表中显示隐式这种关系。

但是,您拥有它的方式不会起作用,因为您错过了 每个项目必须 所需的唯一数据,这将是将 唯一的唯一键 添加到您决定的任何表中。那条数据是SKU。您需要SKU来区分项目与所有其他项目。就像我说的,每个项目都有一个独特的SKU,如果它现在没有,那么你必须发明一个,否则它将是一个噩梦:它将无法工作。

所以你的主表应该是这样的:

  SKU  Name   length  width   On-hand   Reorder-level   Supplier
------------+-------+-------+---------+---------------+--------------- 
  321  stud    6'     2.5      21          4           Studs 'R' Us
  654  stud    8'     3.5      10          8           Studs and More        
  987  stud   10'     2.5      15         10           All Metal Stuff
  101  track  10'     1.0      45         25           Try Us First
  111  track  12'     1.5      22         15           Main St. Track
------------+-------+-------+---------+---------------+--------------- 

您的仪表(不仅仅是仪表)可能是:

  SKU         Gauge   Type     Finish   Application  
------------+-------+--------+--------+------------- 
 321          .05    Normal    shiny     Outdoor    
 654          .05    Normal    dull      Out/In   
 987          .08    Light     paint     Indoor
 101          .08    HvyDuty   dull      Outdoor
 111          .60    Normal    shiny     Out/In

您可能还需要一个最大负载字段,用于客户来电并询问“每4英尺长的轨道可以悬挂多少个灯具?”

也许你想要一张价格表:

  SKU          Qty    Price  
------------+-------+-------- 
 321          each      3.50    
 321            25     86.00    
 321           100    330.00    
 654          each      3.15  
 987          each      2.75
 101          each      4.25
 111           100     46.75

这样的事情。关键是每个表中的主键是SKU,只要每个表中的每一行都有唯一的SKU字段,就可以拥有任意数量的表。

现在你可以通过从一个或多个(你喜欢的)表中选择你想要的任何字段来应用父子关系,例如:给我所有闪亮的完成螺柱,单个成本低于5美元数量。或者向我展示规格为.08或更小的所有螺柱。或者[在我遇到所有人之前阻止我!]或许“向我展示所有SKU和现有数量小于或等于重新订购水平数量的物品的名称。”

与曲目相同。

这就是任何熟练工程师数据库设计师都会如何做到这一点,并且布局还具有“标准化”(google it)的优点。你这样做。

祝你好运!

HTH

答案 1 :(得分:1)

可能的替代解决方案

我不是数据库设计方面的专家,所以在继续我之前,我希望得到 Pete Wilson的输入...

材料清单&项material_lists只是一种启动方式 一组material_list_items之间的关系。每个列表项都会 属于一个列表,并且不会将这些列表关联起来 无论如何都是彼此。

* material_lists
id   name         
---+------------+
1  | Widths     |
2  | Gauges     |
3  | TrackType  |

* material_list_items
id   name         list_id
---+------------+---------+
1  | 3 5/8      | 1       | 
2  | 6          | 1       |
3  | 25ga       | 2       |
4  | 20ga       | 2       |
5  | Regular    | 3       |
6  | Deflection | 3       |

材料组material_groups将是一种创建级联的方法 一组材料之间的关系。每个组/子组可以是一个 A)的方式将其他子组合在一起,和/或 B)分配一个 material_list到项目与关系相关的组。 每个组可以有一个列表(尽管列表可以重复使用)。

* material_groups
id   name         parent_id   list_id 
---+------------+-----------+---------+
1  | Studs      | null      | null    |
2  | Widths     | 1         | 1       |
3  | Gauges     | 2         | 2       |
4  | Track      | null      | null    |
5  | Widths     | 4         | 1       |
6  | Gauges     | 5         | 2       |
7  | TrackType  | 6         | 3       |

<强>材料即可。 materials表将是“生成的”数据集, 每个条目代表一种可能的关系 material_list_itemsmaterial_groups。专栏item_id 代表任何可能的关系的起点 可以从它下来。 例如,从第一个条目开始 (Studs > 3 5/8),将引用此行的其他子条目 将是Studs > 3 5/8 > 25ga&amp; Studs > 3 5/8 > 20gagroup_id列。material_list_items 将是对材料所属的组所引用的参考 在仍然创建单独关系的同时重用#。 不终止(没有孩子)的条目将是“不可参考”的 这张桌子。下表/示例显示了这种关系(请注意* materials (a "generated" list) id item_id parent_id group_id ---+---------+-----------+---------+ 1 | 1 | null | 2 | # Studs > 3 5/8 2 | 2 | null | 2 | # Studs > 6 3 | 3 | 1 | 3 | Studs > 3 5/8 > 25ga 4 | 4 | 1 | 3 | Studs > 3 5/8 > 20ga 5 | 3 | 2 | 3 | Studs > 6 > 25ga 6 | 4 | 2 | 3 | Studs > 6 > 20ga 7 | 1 | null | 5 | # Track > 3 5/8 8 | 2 | null | 5 | # Track > 6 9 | 3 | 7 | 6 | # Track > 3 5/8 > 25ga 10 | 4 | 7 | 6 | # Track > 3 5/8 > 20ga 11 | 3 | 8 | 6 | # Track > 6 > 25ga 12 | 4 | 8 | 6 | # Track > 6 > 20ga 13 | 5 | 9 | 7 | Track > 3 5/8 > 25ga > Regular 14 | 6 | 9 | 7 | Track > 3 5/8 > 25ga > Deflection 15 | 5 | 10 | 7 | Track > 3 5/8 > 20ga > Regular 16 | 6 | 10 | 7 | Track > 3 5/8 > 20ga > Deflection 17 | 5 | 11 | 7 | Track > 6 > 25ga > Regular 18 | 6 | 11 | 7 | Track > 6 > 25ga > Deflection 19 | 5 | 12 | 7 | Track > 6 > 20ga > Regular 20 | 6 | 12 | 7 | Track > 6 > 20ga > Deflection 在我的“不可参考”的想法的每一行的描述旁边。

{{1}}

我意识到这种关系需要在后端进行大量工作,但事实确实如此 我能想到的唯一解决方案是允许我在原版中描述的内容 问题,想看看是否有任何关于成功/痛苦的输入 实施可能是。

我应该选择更简化的内容还是看起来好主意?


Pete响应:快速:您的替代解决方案类似于您提出的第一个解决方案,因此我的评论适用于alt sol。然后:通过在数据库设计问题上强加非数据库结构,您期望实现什么样的实际利益?除了在美学上令你满意之外,我看不出任何奖励。然后:你的桌子都搞混了。对于数据库而言,您几乎可以采用最糟糕的路径。再次,为什么你为什么坚持一个不是数据库解决方案的结构呢?如果你坚持下去,你将在下个月开枪自杀。任何“级联关系”应该(必须是,如果你想要保持理智)以访问数据库而不是结构的方式表达/实现。

您可以通过仔细阅读select writeup并在一两天内创造性地思考它来产生关于访问的想法及其表达您所关注的关系的方式。你会有一个明亮的理解,在里面它将成为你的解决方案。