我需要在时间轴中存储每天的值,即每个数据库用户都应该为每天分配状态,如下所示:
from 1.1.2000 to 28.05.2011 - status 1
from 29.05.2011 to 30.01.2012 - status 3
from 1.2.2012 to infinity - status 4
每天应该只分配一个状态,并且最后状态不会结束(直到给出另一个状态)。我的问题是什么是sql数据库中的有效表示?显而易见的解决方案是为每个更改创建行(在每个范围内分配状态的最后一天),如下所示:
uptodate status
28.05.2011 status 1
30.01.2012 status 3
01.01.9999 status 4
这有很多问题 - 如果我想添加另一个范围,比如从2012年2月15日开始,我还需要改变最后一行:
uptodate status
28.05.2011 status 1
30.01.2012 status 3
14.02.2012 status 4
01.01.9999 status 8
并且需要进行大量检查以确保没有重叠和错误,特别是如果有人想要修改列表中间的范围 - 从29.01.2012插入新状态到10.02.2012很难实现(它需要状态3和状态4的数据范围相应地缩小以为新状态腾出空间)。有没有更好的解决方案?
我想到了完整的其他解决方案,比如将每一天的状态存储在单独的行中 - 因此在时间轴中每天都会有行。这样可以轻松更新 - 只需在开始和结束之间输入日期的行的新状态。当然这会产生大量不必要的数据,因此这是一个糟糕的解决方案,但是连贯且易于管理。我想知道中间是否有什么东西,但我猜不是。
更多上下文:我希望版主能够自由地为任何日期分配状态,并在需要时编辑它。但大多数情况下,主持人最后会添加新的状态数据范围。我真的不需要最后的状态。在主持人完成整月编辑后,我需要根据当月每天的状态生成raport。但是,任何时候主持人可能想要在几个月前编辑数据(这将反映在更新的raports上),并且他可以提前一年提供一个状态。
答案 0 :(得分:1)
您似乎想要将此表用于两件事 - 记录当前状态和状态更改的历史记录。您应该将当前状态分开并将其移至父级(就像注册日期一样)
User
===============
Registered Date
Current Status
Status History
===============
Uptodate
Status
答案 1 :(得分:0)
您的表格结构应包含状态期间的有效日期和结束日期。这有效地将状态“平铺”为不重叠的组。最后一行应该有一个虚拟结束日期(如上所述)或NULL。如果在结束日期有索引,则使用值而不是NULL非常有用。
使用此结构,要获取任何给定日期的状态,请使用查询:
select *
from t
where <date> between effdate and enddate
要在期末添加新状态,需要进行两项更改:
我会将它包装在存储过程中。
要更改过去某个日期的状态,需要将其中一个历史记录拆分为两个。多个日期可能需要更改多个记录。
如果您有日期范围,则可以使用查询获取与给定时间段重叠的所有切片:
select *
from t
where <periodstart> <= enddate and <periodend> >= effdate