规范化表格6

4

我正在制作一个需要进行规范化的数据库,但遇到了一个我不知道该如何处理的问题。

我准备了一个简单的例子来说明这个问题:

Item ID___Mass___Procurement__Currency__________Amount
0__________2kg___inherited____null________________null
1_________13kg___bought_______US dollars_________47.20  
2__________5kg___bought_______British Pounds______3.10
3_________11kg___inherited____null________________null   
4__________9kg___bought_______US dollars__________1.32

对于上面的表格,我有一个属性(Amount),它在功能上依赖于项目ID(我认为),但并非每个项目ID都存在(因为继承的项目没有货币成本)。我相对新手数据库,但我无法在任何初学者教程或文献中找到类似的问题。任何帮助将不胜感激。

4个回答

2

我将创建两个新表 ItemProcurementCurrencies

根据提供的数据,如果金额是物品本身采购的一部分(当物品没有被继承时),我会将 AmountCurrencyID 字段分组在新实体 ItemProcurement 中。

可以看到,继承的物品不会在 ItemProcurement 表中有条目。

关于主要的 Item 表,如果您只期望两种不同的采购方式,则可以使用一个 char(1) 列(从 B => 购买,I => 继承)。

它应该像这样:

enter image description here

数据将如下所示:

TABLE Items
+-------+-------+--------------------+
|    ID |  Mass |  ProcurementMethod |
|-------+-------+--------------------+
|     0 |     2 |                  I | 
+-------+-------+--------------------+
|     1 |    13 |                  B | 
+-------+-------+--------------------+
|     2 |     5 |                  B | 
+-------+-------+--------------------+

TABLE ItemProcurement
+--------+-------------+------------+
| ItemID |  CurrencyID |     Amount |
|--------+-------------+------------+
|     1  |         840 |      47.20 | 
+--------+-------------+------------+
|     2  |         826 |       3.10 | 
+--------+-------------+------------+

TABLE Currencies
+------------+---------+-----------------+
| CurrencyID | ISOCode |     Description |
|------------+---------+-----------------+
|        840 |     USD |      US dollars | 
+------------+---------+-----------------+
|        826 |     GBP |  British Pounds | 
+------------+---------+-----------------+

这允许您以不同的成本和不同的货币类型采购多个相同类型的物品。我错过了那个但。 - XIVSolutions

1

不仅Amount,一切都取决于ItemID,因为这似乎是候选键。

你所依赖的是,当Procurement'inherited'(或者像@XIVsolutions指出的0成本以及你提到的"inherited items have no monetary cost")时,CurrencyAmount都是NULL(我猜这意味着未知/无效)

换句话说,物品分为两种类型(采购方式),其中一种类型的物品没有所有属性。

这可以通过超类型/子类型拆分来解决。您有一个超类型表(Item)和两个子类型表(ItemBoughtItemInherited),每个子类型表都与超类型表具有1::0..1关系。所有物品共有的属性将在超类型表中,每个其他属性都在相应的子类型表中:

Item
----------------------------
ItemID    Mass   Procurement
0          2kg   inherited
1         13kg   bought
2          5kg   bought
3         11kg   inherited 
4          9kg   bought

ItemBought
---------------------------------
ItemID    Currency         Amount
1         US dollars       47.20  
2         British Pounds    3.10 
4         US dollars        1.32

ItemInherited
-------------
ItemID
0       
3    

如果没有仅继承项拥有的属性,则可以完全跳过ItemInherited表。

对于与此模式相关的其他问题,请查找标签:Class-Table-Inheritance。在此过程中,您还可以查找Shared-Primary-Key。对于更概念性的处理,请在Google上搜索“ER Specialization”。


在这种情况下,我认为继承物品的成本只是零,而不是空值。 - XIVSolutions
@XIVSolutions:我认为这并不影响规范化。它是一个常数(我同意0是合理的),在整个“ItemInherited”表中都是常量。 - ypercubeᵀᴹ
我认为OP在初学者的角度下遇到的问题之一是他的表中有些项目的成本值为null。我试图明确表达你所说的,即这个问题不是规范化的问题。 - XIVSolutions
我认为将继承项提取到它们自己的表中没有任何价值。它们仍然是一个项目,具有OP提出的模式中任何其他项目的所有相同属性。一旦空值问题被消除,它们就是同一种东西,并且应该属于同一个表中。 - XIVSolutions
@XIVSolutions:那你如何处理部分依赖关系?(采购='继承' -> 成本=0) - ypercubeᵀᴹ

1

这是我的即兴建议:

更新:Mass应该是Float/Decimal/Double,具体取决于您的数据库,Cost应该是处理货币的最佳类型(在SQL Server 2008中,它是“Money”,但这些东西因情况而异)。

另一个更新:继承物品的成本应该为零,而不是null(实际上,有时会有间接成本,以税收的形式存在,但我岔开了话题...)。因此,您的物品表应要求成本的值,即使该成本为零。它不应该是null。

如果您有问题,请告诉我...

enter image description here


糟糕,"Item"表中的"ProcurementMethodID"拼错了。抱歉... - XIVSolutions

1

为什么需要对其进行规范化?

我可以看到一些数据完整性方面的挑战,但没有明显的结构问题。

“采购”与值/货币的存在或不存在之间的隐式依赖关系很棘手,但与键无关,因此在实际上并不是什么大问题。

如果我们要成为纯粹主义者(例如这是为了作业目的),那么我们正在处理两种类型的项目,即继承项目和购买项目。由于它们不是同一类型的东西,因此应将它们建模为两个单独的实体,即InheritedItem和BoughtItem,并仅使用它们所需的列。

为了获得所有项目的组合视图(例如获得总重量),您将使用视图或UNION sql查询。

如果我们要在数据库中进行对象建模,则可以分离出共同的超类型(Item),并使用外键将子类型(InheritedItem、BoughtItem)建模为超类型表(ypercube解释如下) ,但这非常复杂,比仅对子类型进行建模不太具有未来可扩展性。

这个问题一直存在争议,但实际上,在我的经验中,将具体的超类型建模到数据库中比将它们保持抽象更容易导致后续问题。好吧,这可能远远超出了你想要的范围 :)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接