我们正在使用以下MySQL表来维护用户信用。
id user credits expiry status
-----------------------------------------
1 A 1.2 somedatetime 0
2 A 4.4 somedatetime 0
3 A 5.0 somedatetime 0
4 B 1.0 somedatetime 0
5 B 2.4 somedatetime 0
6 C 7.8 somedatetime 0
每当用户进行购买时,我们会从可用的积分中扣除金额。为了对用户公平,最近到期的信用将首先消耗,依此类推。我们还将更新状态以将行标记为已消耗。
例如,如果用户A购买了2美元,则1.2美元将从ID 1中扣除,剩余的美元将从ID 2中扣除,依此类推。所以表现在看起来像
id user credits expiry status
-----------------------------------------
1 A 0.0 somedatetime 1
2 A 3.6 somedatetime 1
3 A 5.0 somedatetime 0
4 B 1.0 somedatetime 0
5 B 2.4 somedatetime 0
6 C 7.8 somedatetime 0
到目前为止,我们一直采用蛮力方法。任何想法建议如何在最小或单个查询中更有效地做到这一点。
更新:由于有人询问我们当前的暴力方法,它会从最早的那一行开始迭代并更新,直到购买金额被覆盖,效率非常低。
由于
答案 0 :(得分:3)
使用变量计算总计学分。运行内部查询,以便首先了解beign计算的内容。
<强> Fiddle Demo 强>
CREATE TABLE customer
(`id` int, `user` varchar(1), `credits` double, `expiry` int, `status` int)
;
INSERT INTO customer
(`id`, `user`, `credits`, `expiry`, `status`)
VALUES
(1, 'A', 1.2, 1, 0),
(2, 'A', 4.4, 2, 0),
(3, 'A', 5.0, 3, 0),
(4, 'B', 1.0, 4, 0),
(5, 'B', 2.4, 5, 0),
(6, 'C', 7.8, 6, 0)
;
CREATE TABLE credits
(`id` int, `user` varchar(1), `credit_used` double)
;
INSERT INTO credits
(`id`, `user`, `credit_used`)
VALUES
(1, 'A', 2.0),
(2, 'B', 3.4)
;
我的测试设置:
Application.EnableEvents = True
答案 1 :(得分:0)
http://sqlfiddle.com/#!9/485673/1
SET @amount = 2;
UPDATE t1
JOIN (
SELECT t2.id,
IF(@amount=0,t2.credits, IF(@amount>t2.credits,0,t2.credits-@amount)) credits,
IF(@amount>=t2.credits,@amount := @amount-t2.credits, 0)
FROM (
SELECT id, credits
FROM t1
WHERE credits>0 AND `user`='A'
ORDER BY expiry ASC
) t2
) t
ON t1.id = t.id
SET t1.credits=t.credits
WHERE t1.user = 'A';