这是一个虚构的场景,其中包含一些填充的数据。出于税收目的,我的虚构公司必须保留历史数据记录。出于这个原因,我在表中包括了一个version列。
TABLE EMPLOYEE: (with personal commentary) |ID | VERSION | NAME | Position | PAY | +---+---------+------------+----------+-----+ | 1 | 1 | John Doe | Owner | 100 | Started company | 1 | 2 | John Doe | Owner | 80 | Pay cut to hire a coder | 2 | 1 | Mark May | Coder | 20 | Hire said coder | 2 | 2 | Mark May | Coder | 30 | Productive coder gets raise | 3 | 1 | Jane Field | Admn Asst| 15 | Need office staff | 2 | 3 | Mark May | Coder | 35 | Productive coder gets raise | 1 | 3 | John Doe | Owner | 120 | Sales = profit for owner! | 3 | 2 | Jane Field | Admn Asst| 20 | Raise for office staff | 4 | 1 | Cody Munn | Coder | 20 | Hire another coder | 4 | 2 | Cody Munn | Coder | 25 | Give that coder raise | 3 | 3 | Jane Munn | Admn Asst| 20 | Jane marries Cody <3 | 2 | 4 | Mark May | Dev Lead | 40 | Promote mark to Dev Lead | 4 | 3 | Cody Munn | Coder | 30 | Give Cody a raise | 2 | 5 | Mark May | Retired | 0 | Mark retires | 5 | 1 | Joey Trib | Dev Lead | 40 | Bring outside help for Dev Lead | 6 | 1 | Hire Meplz | Coder | 10 | Hire a cheap coder | 3 | 4 | Jane Munn | Retired | 0 | Jane quits | 7 | 1 | Work Fofre | Admn Asst| 10 | Hire Janes replacement | 8 | 1 | Fran Hesky | Coder | 10 | Hire another coder | 9 | 1 | Deby Olav | Coder | 25 | Hire another coder | 4 | 4 | Cody Munn | VP Ops | 80 | Promote Cody | 9 | 2 | Deby Olav | VP Ops | 80 | Cody fails at VP Ops, promote Deby | 4 | 5 | Cody Munn | Retired | 0 | Cody retires in shame | 5 | 2 | Joey Trib | Dev Lead | 50 | Give Joey a raise +---+---------+------------+----------+-----+
现在,如果我想做类似“获取当前编码员列表”之类的事情SELECT * FROM EMPLOYEE WHERE Position = 'Coder',那我就不能做,因为那样会返回很多历史数据……这很糟糕。
SELECT * FROM EMPLOYEE WHERE Position = 'Coder'
我正在寻找解决这种情况的好主意。我看到了一些选择,但我确定有人会说:“哇,那是菜鸟的错误,发亮……试穿这种尺码:”这就是这个地方的全部,对不对?:-)
想法1: 使用这样的当前版本保存版本表
TABLE EMPLOYEE_VERSION: |ID |VERSION| +---+-------+ | 1 | 3 | | 2 | 5 | | 3 | 4 | | 4 | 6 | | 5 | 2 | | 6 | 1 | | 7 | 1 | | 8 | 1 | | 9 | 2 | +---+-------+
尽管我不确定如何通过单个查询来做到这一点,但是我敢肯定它可以做到,而且我敢打赌,我可以花很少的精力就可以解决这个问题。
当然,我每次插入EMPLOYEE表时都必须更新此表,以增加给定ID的版本(或在创建新ID时插入版本表)。
这样的开销似乎是不希望的。
想法2: 保留一个存档表和一个主表。在更新主表之前,将要覆盖的行插入存档表,然后像往常一样使用主表,就好像我不关心版本控制一样。
想法3: 找到一条添加 如下 内容的查询SELECT * FROM EMPLOYEE WHERE Position = 'Coder' and version=MaxVersionForId(EMPLOYEE.ID)…不确定我该怎么做。对我来说,这似乎是最好的主意,但我目前还不确定。
SELECT * FROM EMPLOYEE WHERE Position = 'Coder' and version=MaxVersionForId(EMPLOYEE.ID)
想法4: 在“当前”列中添加“当前=真实AND …”
在我看来,人们肯定已经做过,遇到了同样的问题,并且有见识可以分享,所以我来收集一下!:)我已经尝试在此处查找问题的示例,但是它们似乎专用于特定情况。
谢谢!
编辑1:
首先,我感谢所有答案,并且你们都说过同样的话-DATE比更好VERSION NUMBER。我要使用的原因之一是VERSION NUMBER简化服务器中的更新过程,以防止出现以下情况
DATE
VERSION NUMBER
人员A在其会话中加载员工记录3,并且具有版本4。人员B在其会话中加载员工记录3,并且具有版本4。人员A进行更改和提交。之所以可行,是因为数据库中的最新版本是4。现在是5。人员B进行更改并提交。失败是因为最新版本是5,而他的版本是4。
EFFECTIVE DATE模式将如何解决此问题?
EFFECTIVE DATE
编辑2:
我想我可以通过以下操作来做到这一点:人员A在他的会话中加载了员工记录3,其生效日期为2010年1月1日,下午1:00,无任何延期。B员工在其会话中加载员工记录3,其生效日期为2010年1月1日,下午1:00,无任何费用。人员A进行更改并提交。旧副本进入存档表(基本上是概念2),有效期为9/22/2010 1:00 pm。主表的更新版本的生效日期为9/22/2010 1:00 pm。人B进行更改并提交。提交失败,因为有效日期(在数据库和会话中)不匹配。
我认为您已经走错了路。
通常,对于版本控制或存储历史数据,您需要执行两项(或两项)操作之一。
您有一个单独的表,该表模仿原始表+一个更改日期的日期/时间列。每当记录更新时,就在更新之前将现有内容插入到历史表中。
您有一个单独的仓库数据库。在这种情况下,您可以像上面的#1中那样对它进行版本控制,也可以仅每隔一段时间(每小时,每天,每周)对其快照一次。
将您的版本号与普通表放在同一张表中会遇到一些问题。首先,表的大小将变得疯狂。这将对正常的生产查询造成持续的压力。
其次,它将从根本上增加联接等的查询复杂度,以确保使用每个记录的最新版本。