这让我怀疑了一段时间,所以我认为在这里发布它以找到一些见解是一个好主意,这是关系数据库建模问题/怀疑
我有以下问题:
我有“问题”必须处于特定的“状态”,所有状态的变化都必须经过审核。
我找到了两个解决方案,但是我真的看不出它们之间的区别,如果有的话......你觉得怎么样。
这是两张图的图像。
修改
选项A:表“questions”不应包含state_id,而Question_State不应包含“id”字段。抱歉错误。
EDIT2 :
感谢所有现实世界的例子和见解,但这是一个学术问题,而不是与现实相关的问题:)。
答案 0 :(得分:5)
我认为你要问的要点是:问题的状态是否应该基于问题和状态之间的中间表,该表具有时间组件(A)或表格应该更加静态,但是侧面的面向日志的历史表(B)。
(注意:如果你想做一个(A)的纯版本,那么Boofus是对的,你可能也不会把state_id放在Questions表中,因为它是多余的;但这肯定是不方便的,因为它会进行简单的查询,以便在特定的状态下更难获得问题。所以你在这里有一个混合版本。)
一般而言,如果保留有关状态的历史信息的要求实际上仅用于审计目的 - 也就是说,如果应用程序本身不会定期查询 - 那么最好选择B,因为它有点简单(实际上只有一个“问题”表,带有状态的参考表,以及以前状态的“日志”表)。我认为这表明你的意图好一点。
但是,如果应用程序语义更复杂(例如,如果您有“显示过去24小时内处于状态X的所有问题......”这样的查询,那么像(A)这样的方法可能会使更有意义。它实质上是将问题的状态变成与时间相关的事实。如果你这样做,只要知道它使事情变得复杂 - 要么你的所有查询都更难以考虑时间,要么你必须担心问题上的state_id与Questions表中的最新状态保持同步。如果你走这条路线,可能会把它称为“current_state”或类似的问题,所以很明显它是衍生信息。
答案 1 :(得分:1)
您可能希望在“时态数据库”主题上搜索网页。基本上,存储任何变量的变化历史都会引发相同的问题,无论变量是否捕获问题状态或人的体重等等。
其次,我认为您的问题与数据库设计有关,而与概念数据建模无关。如果我让你的漂移正确,你就会问哪种桌子设计更好。
第三,我更喜欢选项B,但这实际上取决于你将如何处理数据。
我询问数据库设计与概念建模的原因是我很久以前采用了将“实体和关系”用于与数据分析相关的概念数据建模的实践。在讨论逻辑数据库设计时,我使用术语“表,列和行”。保持分析和设计分离在大型项目中非常有价值。并不像听起来那么容易。
你真的应该在选项B的图表中的Historical表和State表之间添加一个箭头。图表的呈现方式,它几乎看起来像Historical表是一个不相交的表。在这个简单的例子中不是问题,但是当你扩展到包含数十个表的数据库时,如果你保持相同的做法,你最终会混淆每个看图的人。
答案 2 :(得分:0)
一旦你了解了所有关系,它们就是一样的。
我不明白为什么你在问题表中有state_id - 因为你有历史表,问题表中的状态是多余的,可能会给你带来不同步的数据。
在我看来,如果你想要问题的当前状态,你可以
SELECT State_ID FROM Historical WHERE Question_id =? ORDER BY日期DESC限制1
(或者你的SQL风格用来限制只有1行的任何方法)
答案 3 :(得分:0)
假设您在数据库和OO之间有很好的抽象层,您可以考虑将State表从数据库中取出并使其成为类中的枚举。它不一定需要持久化。
然后在Questions表和审计表中使用State列。
答案 4 :(得分:0)
您说经过审核,这意味着您只是希望保留历史信息以用于报告目的。在这种情况下,我建议图B更清楚,尽管你应该标记问题与历史,州与历史之间的一对多关系。
至于实际情况,如果情况如上,我自己将历史插入功能封装到问题的插入/更新触发器中,如果问题表的数量和/或状态更改的数量是重要的是我会考虑将历史表放在不同的数据库中。这只是稍后简化数据库管理。通常我对触发器持谨慎态度,因为过度使用会导致难以维护的数据库(因为它不会立即显示正在发生的事情),但这是一个明显的例子,它们非常适合并且是使用的最佳选择应用逻辑。
顺便提一下,你的两个图表都暗示一个问题只能进入每个州一次(来自你的PK) - 你应该考虑这是否正确,因为在大多数现实世界的应用程序中会出现错误并且状态会逆转。
答案 5 :(得分:0)
我不像#Boofus那样理解在问题表中有一个state_id字段的兴趣。
在我们自己的应用程序中,我一直在使用这种“状态”概念。在大多数复杂情况下,我们必须跟进完整的状态历史记录以及对象可以具有多个状态的情况,我们使用以下模型:
对于多状态情况,我们的想法是检查end_date值是否为null(另一个想法是在表中有一个布尔字段isActiveState)。不要低估拥有这种“多状态”配置的兴趣。例如:
问题可以是
或强>
这可能对应于两种不同的状态:
或强>
但我认为最好的解决方案是同时拥有
和强>
并允许问题具有多个状态