【问题标题】:Storing expirable credits in database?在数据库中存储过期信用?
【发布时间】:2015-05-06 02:35:56
【问题描述】:
在用户表中使用额外的列很容易存储用户信用,例如user_credits,现在是一个额外的要求
- 对于添加到
user_credits 列的每个积分,如果未使用,它将在一年后自动过期。
我当然需要一个额外的表来存储过期信息,例如
[table credits_history]
user_id
credits
used
created_at
所以,在消费积分时,我需要
- 检查
user_credits是否足够消费
- 循环所有
credits_history表中used = 0 AND now - created_at < 1yr的用户信用,并设置used to 1
- 更新
user_credits
最后,我需要通过查看created_at 来设置每日 cron 作业以更新 user_credits
上述方法合理吗?或者任何标准的方式来处理上述要求?
【问题讨论】:
标签:
mysql
sql
database
database-design
database-schema
【解决方案1】:
不要存储您可以计算的东西,除非计算成本太高。假设credits_history 中每个用户的行数不太高,您可以构建查询以检查可用积分的总和:
SELECT SUM(credits-consumed) -- see more about "consumed" below
FROM credits_history
WHERE user_id=?
AND created_at >= DATE_SUB(NOW(),INTERVAL 1 YEAR)
这种方法的另一个好处是您不再需要 cron 作业来维护 user_credits。
消耗积分变得有点棘手:您需要添加一列来显示已使用的积分部分。这里有一个例子来说明这一点。假设用户在他的历史记录中添加了这些信用:
created_on credits consumed
---------- ------- --------
05/06/2014 50 0
07/12/2014 70 0
12/01/2014 40 0
如果您运行上面的查询,您将得到 160 的总和。
现在他想消耗 90 积分。您的代码应查询所有符合条件的信用记录,从最旧到最新对它们进行排序,并根据需要使用尽可能多的信用来支付所需的金额(即 90)
created_on credits consumed
---------- ------- --------
05/06/2014 50 50
07/12/2014 70 40
12/01/2014 40 0
现在上面的查询将得到 70 的总和。
【解决方案2】:
不,我不认为这是一种正常的方法。通常你会有一个像 user_credits 这样的表,每个用户可以有多行,每个这样的行都有剩余信用和到期日期(我认为我更喜欢到期日期而不是 created_at,因为你只计算一次)。但是你会有一个交易表,其中列出了贷方/借方(正/负贷方)。购买积分将创建添加该数量积分的交易。使用积分将创建一个被扣除的积分金额的交易。即将到期的积分只是另一笔被扣除的积分交易。每笔交易还会更新 user_credits 中的剩余信用。
唯一烦人的是,要计算用户的当前信用,您必须转到 user_credits 并将该用户的所有行加起来。有些人可能会跟踪主用户表中的另一个值以绕过它。
可以通过 cron 作业来整理该表来完成过期信用。虽然如果你想小气一点,你也可以在交易时检查到期日期,以确保没有人在 cron 作业之前偷偷溜进来。
【解决方案3】:
我会这样做
表:USER (id,name,address,phone,etc)
表:CREDIT_TYPE(id,description, expiration_policy, etc)
表:USER_CREDIT(user_id, credit_type_id, activation_date, expiration_date)
- 用户有零个或多个积分
- 每个信用都有某种到期政策、规则等
- 如果 CURRENT_DATE > expiration_date,则信用过期
到期日期是根据 credit_type 上规定的政策立即设置的
这行得通吗?