0

I need to store values for every day in timeline, i.e. every user of database should has status assigned for every day, like this:

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

Each day should have only one status assigned, and last status is not ending (until another one is given). My question is what is effective representation in sql database? Obvious solution is to create row for each change (with the last day the status is assigned in each range), like this:

uptodate     status
28.05.2011   status 1
30.01.2012   status 3
01.01.9999   status 4

this has many problems - if i would want to add another range, say from 15.02.2012, i would need to alter last row too:

uptodate     status
28.05.2011   status 1
30.01.2012   status 3
14.02.2012   status 4
01.01.9999   status 8

and it requires lots of checking to make sure there is no overlapping and errors, especially if someone wants to modify ranges in the middle of the list - inserting a new status from 29.01.2012 to 10.02.2012 is hard to implement (it would require data ranges of status 3 and status 4 to shrink accordingly to make space for new status). Is there any better solution?


i thought about completly other solution, like storing each day status in separate row - so there will be row for every day in timeline. This would make it easy to update - simply enter new status for rows with date between start and end. Of course this would generate big amount of needless data, so it's bad solution, but is coherent and easy to manage. I was wondering if there is something in between, but i guess not.


more context: i want moderator to be able to assign status freely to any dates, and edit it if he would need to. But most often moderator will be adding new status data ranges at the end. I don't really need the last status. After moderator finishes editing whole month time, I need to generate raport based on status on each day in that month. But anytime moderator may want to edit data months ago (which would be reflected on updated raports), and he can put one status for i.e. one year in advance.

4

2 回答 2

1

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

User
===============
Registered Date
Current Status

Status History
===============
Uptodate 
Status
于 2012-05-28T16:52:40.797 回答
0

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

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

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

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

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

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

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

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

select *
from t
where <periodstart> <= enddate and <periodend> >= effdate
于 2012-05-28T23:07:05.530 回答