存储数据范围 - 有效表示



我需要在时间轴中存储每天的值,即数据库的每个用户都应该为每天分配状态,如下所示:

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

这有很多问题 - 如果我想添加另一个范围,比如从 15.02.2012 开始,我也需要更改最后一行:

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上),并且他可以提前一年放置一个状态,即一年。

您似乎想将此表用于两件事 - 记录当前状态和状态更改的历史记录。您应该将当前状态分离出来并将其移至父级(就像注册日期一样)

User
===============
Registered Date
Current Status
Status History
===============
Uptodate 
Status

您的表格结构应包括状态期的生效日期和结束日期。 这有效地将状态"平铺"为不重叠的组。 最后一行应该有一个虚拟的结束日期(如上所示)或 NULL。 如果在结束日期有索引,则使用值而不是 NULL 很有用。

使用此结构,若要获取任何给定日期的状态,请使用查询:

select *
from t
where <date> between effdate and enddate

要在期末添加新状态,需要进行两项更改:

  1. 修改表中结束日期 = 01/01/9999 的行,使其结束日期为昨天。
  2. 插入一个新行,其有效期为今天,结束日期为 01/01/9999

我会把它包装在一个存储过程中。

要更改过去某个日期的状态,需要将历史记录之一一分为二。 多个日期可能需要更改多个记录。

如果您有日期范围,则可以获取与查询重叠给定时间段的所有磁贴:

select *
from t
where <periodstart> <= enddate and <periodend> >= effdate

最新更新