1

假设您有两组概念实体:

  • 具有多个ForwardPriceEntries的MarketPriceDataSet
  • 具有多个PoolPriceForecastEntry的PoolPriceForecastDataSet

两个不同的子对象具有几乎相同的字段:

ForwardPriceEntry 有

  • 开始日期
  • 结束日期
  • 模拟项 ID
  • 远期价格
  • MarketPriceDataSetId(父表的外键)

PoolPriceForecastEntry 有

  • 开始日期
  • 结束日期
  • 模拟项 ID
  • 预测池价格
  • PoolPriceForecastDataSetId(父表的外键)

如果我将它们建模为单独的表,唯一的区别就是外键和价格字段的名称。

关于是否应将两个几乎相同的表合并为一个的问题一直存在争议。

我想到的建模选项是:

  • 只需将它们保留为两个独立的单独表格
  • 将两个集合放在一个表中,并带有一个附加的“类型”字段,并且parent_id等于任一父表的外键。这将牺牲参照完整性检查。
  • 将这两个集合放在一个带有附加“类型”字段的表中,并创建一个复杂的连接表序列以保持引用完整性。

你认为我应该怎么做,为什么?


其他可能相关或不相关的信息:

  • 这两组数据是松散相关的:每组将加载到内存中进行批处理,偶尔会通过从 ForwardPriceEntries 复制生成一组PoolPriceForecastEntries

  • MarketPriceDataSetPoolPriceForecastDataSet确实有不同的字段。可以将它们合并到一个表中,但是您将在一半条目中拥有无意义的字段。

4

4 回答 4

3

“关于这两个几乎相同的表是否应该合并为一个问题一直存在争议。”

有吗?

在数据库设计中,如果谓词不同,表应该保持独立。也就是说,如果表中各行所附加的含义不同。列集是否几乎或什至完全相等,无关紧要。

于 2010-03-19T19:43:09.113 回答
3

很多时候,在您描述的情况下,被建模的主题符合一种称为“泛化专业化”的模式。两个先前的答案讨论子类型的事实支持了这一点。对象模型倾向于通过使用子类型和继承来处理 gen-spec。

关系模型也可以处理 gen-spec,但它有点复杂,并且通常不会在数据库入门中教授。你要做的是有几个表,每个子类型一个,保存子类型特有的键和非键属性。与超类型相关并由所有子类型继承的数据通常合并到一个表中。

您可以使用这些表的键来玩一个技巧,以减少存储和处理。在子类型表中,使用返回超类型条目的外键作为子类型表的主键。它保证存在,并且保证是唯一的。为什么还要费心发明另一把钥匙?

如果您搜索“泛化专业化关系建模”,您将获得有关该主题的十几篇文章。其中一些非常好。也可以关注标签:

于 2010-03-19T12:38:47.803 回答
1

由于实体共享如此多的属性,您可以将它们视为子类型。

从逻辑上讲,您将拥有 PriceEntry 的超类型以及 ForwardPriceEntry 和 PoolPriceForecastEntry 的子类型。要回答的一个问题是价格对于超类型是否通用。我会假设它是。

现在的问题是如何物理实现子类型。您可以采取 3 种方法:

  1. 为每个子类型创建一个表(Rolldown)
  2. 创建具有所有属性的单个表(汇总)
  3. 为每个子类型(身份)创建一个超类型表和一个子类型表

这些方法中的每一种都有优点和缺点。有关每种方法的优缺点的讨论,请参阅Getting Physical with Subtypes

在这种情况下,由于子类型共享这么多属性,您可以采用汇总方法并创建一个表。

PriceEntry 表可能如下所示:

PriceEntryId (PK)
PriceEntryTypeCode (NN)
StartDate (NN)
EndDate 
SimulationItemId (NN)
Price (NN)
MarketPriceDataSetId (FK)
PoolPriceForecastDataSetId (FK)

您仍然可以在 MarketPrice 和 PoolForecast 列上强制执行 FK。您还可以添加表级检查约束以确保至少填充一个 FK。


但是,由于 2 个子类型之间只有一个属性不同,因此许多优点和缺点并不强烈指向一个方向。所以,最后,我可能会选择让数据模型易于理解和使用。对我来说,两张表(rolldown)方法取得了很好的平衡;从概念上讲,它比汇总更容易理解,并且在开发时它比标识更容易使用(没有连接或多次插入/更新)。

于 2010-03-19T06:27:52.983 回答
0

如果您打算以大致相同的方式使用来自两个子类型的数据,我建议将所有数据放入包含所有五个字段的单个表中......

  • 开始日期
  • 结束日期
  • 模拟项 ID
  • 远期价格
  • MarketPriceDataSetId(父表的外键)

... 并将 null 放入 ForwardPrice 或 ForecastPoolPricedepending 字段,等待特定行支持的父实体。每行空值的空间成本几乎不存在,压缩成功在表上会非常高,但对于索引和读取,您的性能会令人印象深刻。

于 2010-03-19T03:48:12.980 回答