Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 根据列的总和更新最早的行_Mysql_Sql - Fatal编程技术网

Mysql 根据列的总和更新最早的行

Mysql 根据列的总和更新最早的行,mysql,sql,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

我们有一个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,则id 1将借记$1.2,id 2将借记$0.8,依此类推。所以这个表现在看起来像

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  
到目前为止,我们一直采用暴力手段。任何关于如何在最小查询或单个查询中更有效地执行此操作的建议

更新:由于有人询问我们当前的暴力方法,它从最早的一行开始迭代每一行,并不断更新,直到涵盖购买金额,这是非常低效的


感谢您使用变量计算总学分。运行内部查询,以便首先了解什么是beign calculate

UPDATE customer c
JOIN (
        SELECT cu.`id`, 
               cu.`user`, 
               `credits`, `expiry`, `status`,        
               @total := IF(@customer = cu.`user`, @total := @total  + `credits`, `credits`) as cumulative_total,
               @customer := cu.`user` as user_current,
               `credit_used`
        FROM customer cu 
        CROSS JOIN  (SELECT @customer := '', @total := 0 ) t
        JOIN credits
          ON cu.`user` = credits.`user`
        ORDER BY cu.`id`
     ) t
   ON c.`id` = t.`id`
SET c.credits = CASE WHEN c.credits <= t.credit_used THEN 0
                                                     ELSE t.cumulative_total - credit_used
                END,
    c.status =  CASE WHEN c.credits <= t.credit_used THEN 1
                                                     ELSE 0
                END;


有人问过类似的问题。@草莓:请发布链接“暴力手段”是什么意思?@shadow一行一行地阅读并更新,直到购买金额被支付。其中$2,$1.2将从id 1中扣除,剩余$0.6我的数学不是很好,但我还有剩余的0.8
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)
;
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';