根据列的总和更新最旧的行

时间:2016-06-16 14:28:20

标签: mysql sql

我们正在使用以下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  

到目前为止,我们一直采用蛮力方法。任何想法建议如何在最小或单个查询中更有效地做到这一点。

更新:由于有人询问我们当前的暴力方法,它会从最早的那一行开始迭代并更新,直到购买金额被覆盖,效率非常低。

由于

2 个答案:

答案 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';