在谈到具有“历史性”的关系时,我在各种选择之间犹豫不决 值。
例如,假设一个用户在某个特定日期购买了一件商品...如果我只是以经典的方式存储它:
transation_id: 1
user_id: 2
item_id: 3
created_at: 01/02/2010
然后很明显,用户可能会更改其名称,该项目可能会更改其价格,3年后,当我尝试创建有关我有错误数据的报告时。
我有两种选择:
像我之前所说的那样保持愚蠢,但使用像https://github.com/airblade/paper_trail这样的东西,并执行以下操作:
t = Transaction.find(1);
u = t.user.version_at(t.created_at)
创建一个类似transaction_users
和transaction_items
的数据库,并在进行事务时将用户/项复制到这些表中。结构将变为:
transation_id: 1
transaction_user_id: 2
transaction_item_id: 3
created_at: 01/02/2010
这两种方法都有其优点,解决方案1看起来更简单......你看到解决方案1有问题吗?这个“历史数据”问题通常如何解决?对于我的项目,我必须为这样的2-3个模型解决这个问题,你认为什么是最好的解决方案?
答案 0 :(得分:0)
以物品价格为例,你也可以:
在交易表中存储价格副本:
TABLE Transaction(
user_id -- User buying the item
,trans_date -- Date of transaction
,item_no -- The item
,item_price -- A copy of Price from the Item table as-of trans_date
)
获取交易时的价格就是:
select item_price
from transaction;
为商品价格创建时态表:
TABLE item (
item_no
,etcetera -- All other information about the item, such as name, color
,PRIMARY KEY(item_no)
)
TABLE item_price(
item_no
,from_date
,price
,PRIMARY KEY(item_no, from_date)
,FOREIGN KEY(item_no)
REFERENCES item(item_no)
)
第二个表格中的数据会出现类似的内容:
ITEM_NO FROM_DATE PRICE
======= ========== =====
A 2010-01-01 100
A 2011-01-01 90
A 2012-01-01 50
B 2013-03-01 60
从2010年1月1日开始,A条的价格为100.它将2011年1月的第一个改为90个,然后从2012年1月1日再次改为50个。
你很可能会在表中添加一个TO_DATE,即使它是非规范化(TO_DATE是下一个FROM_DATE)。
在交易中查找价格将是:
select t.item_no
,t.trans_date
,p.item_price
from transaction t
join item_price p on(
t.item_no = p.item_no
and t.trans_date between p.from_date and p.to_date
);
ITEM_NO TRANS_DATE PRICE
======= ========== =====
A 2010-12-31 100
A 2011-01-01 90
A 2011-05-01 90
A 2012-01-01 50
A 2012-05-01 50
答案 1 :(得分:0)
我会选择PaperTrail,它保留了我所有模型的历史,甚至是它们的毁灭。如果它不能缩放,我总是可以稍后切换到第2点。