0

这让我怀疑了一段时间,所以我认为将它发布在这里以找到一些见解是个好主意,这是一个关系数据库建模问题/怀疑

我有以下问题:

我有必须处于特定“状态”的“问题”,并且必须审核所有状态更改。

我找到了两种解决方案,但我真的看不出它们之间的区别,如果有的话......你怎么看。

这是两个图表的图像。

编辑:

选项 A:表“questions”不应包含 state_id,并且 Question_State 不应包含“id”字段。对错误感到抱歉。

编辑2

感谢所有现实世界的例子和洞察力,但这是一个学术问题,与现实世界无关:)。

图表

4

6 回答 6

5

我认为您要问的要点是:问题的状态是否应该基于 Questions 和 State 之间的具有时间分量 (A) 的中间表,或者该表是否应该更加静态,但具有面向日志的侧面的历史表(B)。

(注意:如果你想做一个纯版本的(A),那么 Boofus 是对的,你可能不会把 state_id 也放在 Questions 表中,因为它是多余的;但这肯定不方便,因为它会使简单的查询来获得特定状态下的问题要困难得多。所以你在这里有一个混合版本。)

一般来说,如果保留有关状态的历史信息的要求真的只是为了审计目的——也就是说,如果应用程序本身不会定期查询它——你可能最好选择选项 B,因为它是稍微简单一点(实际上只有一个“问题”表,有一个状态参考表,以及一个用于先前状态的“日志”表)。我认为这更好地表明了你的意图。

但是,如果应用程序语义更复杂(例如,如果您有诸如“显示过去 24 小时内处于状态 X 的所有问题......”之类的查询),那么像 (A) 这样的方法可能更有意义。它本质上是把一个问题的状态变成一个与时间相关的事实。如果您这样做,请注意这会使事情变得复杂 - 您的所有查询都更难并且必须考虑时间,或者您必须担心保持 Questions 上的 state_id 与 Questions 表中的最新状态同步。如果你走那条路,也许在 Questions 上称它为“current_state”或其他名称,所以很明显它是一种衍生信息。

于 2008-12-05T17:28:17.047 回答
1

您可能想在网络上搜索“时态数据库”这一主题。基本上,存储任何变量的变化历史都会引发相同的问题,无论该变量是否捕获问题状态或人的体重或其他什么。

其次,我认为您的问题与数据库设计有关,而不是与概念数据建模有关。如果我的想法正确,那么您是在问哪种桌子设计更好。

第三,我更喜欢选项 B,但这实际上取决于您将如何处理数据。

我询问数据库设计与概念建模的原因是,我很久以前就采用了使用“实体和关系”进行与数据分析相关的概念数据建模的做法。在讨论逻辑数据库设计时,我使用术语“表、列和行”。将分析和设计分开在大型项目中非常有价值。而且做起来并不像听起来那么容易。

对于选项 B,您确实应该在图表中的历史表和状态表之间添加一个箭头。图表的呈现方式几乎看起来就像历史表是一个不相交的表。在这个简单的示例中不是问题,但是如果您在扩展到具有数十个表的数据库时保持相同的做法,您最终会混淆查看图表的每个人。

于 2008-12-05T21:48:57.427 回答
0

一旦你画了所有的关系,它们是一样的。

我不明白为什么你在问题表中有 state_id - 因为你有历史表,所以在问题表中拥有状态是多余的,并且可能会给你留下不同步的数据。

在我看来,如果你想要一个问题的当前状态,你可以

SELECT State_ID FROM Historical WHERE Question_id = ? ORDER BY Date DESC LIMIT 1

(或任何您的 SQL 风格用来限制为 1 行的方法)

于 2008-12-05T17:13:27.780 回答
0

假设您在数据库和 OO 之间有良好的抽象层,您可能会考虑将 State 表从数据库中取出并使其成为类中的枚举。这不一定是需要坚持的东西。

然后在 Questions 表和 audit 表中有 State 列。

于 2008-12-05T17:53:56.793 回答
0

您说已审计,这意味着您只是希望保留历史信息以用于报告目的。在这种情况下,我建议图 B 更清晰,尽管您可能也应该标记问题和历史以及状态和历史之间的一对多关系。

至于实用性,如果情况如上所述,我自己会将历史插入功能封装到问题上的插入/更新触发器中,如果问题表的数量和/或状态更改的数量会很大,我会考虑将历史表放在不同的数据库中。这只是简化了以后的数据库管理。通常我对触发器持谨慎态度,因为过度使用会导致数据库难以维护(因为目前还不清楚发生了什么),但这是一个明显的例子,它们非常适合并且是使用的更好选择应用逻辑。

顺便说一句,您的两个图表都暗示一个问题只能进入每个状态一次(从您的 PK 中) - 您应该考虑这是否正确,因为在大多数现实世界的应用程序中都会犯错误并反转状态。

于 2008-12-05T18:02:45.933 回答
0

我不明白,像#Boofus 一样,在 Questions 表中有一个 state_id 字段的兴趣。

在我们自己的应用程序中,我一直在使用这样的“状态”概念进行了大量工作。在大多数复杂情况下,我们必须跟踪完整的状态历史以及对象可以具有多个状态的情况,我们使用以下模型:

替代文字

对于多状态情况,想法是检查 end_date 值是否为空(另一个想法是在表中有一个布尔字段 isActiveState)。不要低估拥有这种“多状态”配置的兴趣。例子:

一个问题可以是

  • 关闭并解决

或者

  • 关闭且未解决。

这可能对应于两种不同的状态:

  • “关闭并解决”状态

或者

  • “已关闭且未解决”状态

但我认为最好的解决方案是同时拥有

  • “打开/关闭”状态

  • “已解决/未解决”状态

并允许问题有多个状态

于 2008-12-07T23:54:25.440 回答