Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.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 更新第一行大于0的字段,直到它达到0,然后从下一行减去?_Mysql_Sql - Fatal编程技术网

Mysql 更新第一行大于0的字段,直到它达到0,然后从下一行减去?

Mysql 更新第一行大于0的字段,直到它达到0,然后从下一行减去?,mysql,sql,Mysql,Sql,是否有方法更新第一行字段,使其大于0并从中减去,直到达到0,然后移动到下一行并继续从中减去 表: 柱 数量 第一 0 第二 5. 第三 5. 您可以使用递归来完成工作。但它只能在MySQL 8.0及更高版本上运行 create table mytable (Columns varchar(50),Amount int); insert into mytable values('First', 0); insert into mytable values('Second', 5);

是否有方法更新第一行字段,使其大于0并从中减去,直到达到0,然后移动到下一行并继续从中减去

表:

柱 数量 第一 0 第二 5. 第三 5.
您可以使用递归来完成工作。但它只能在MySQL 8.0及更高版本上运行

 create table mytable (Columns varchar(50),Amount int);
 insert into mytable values('First',    0);
 insert into mytable values('Second',   5);
 insert into mytable values('Third',    5);
查询:

 with recursive
 cte as
 (
   select Columns,amount,row_number()over(order by Columns) rn from mytable
 )
 , cte2 as
 (
  select Columns, (case when amount0 then (case when amount9 then amount-9 else 0 end) else 0 end)amount,
  (case when amount0 then (case when amount9 then 0 else 9-amount end) else 9 end)remainingamount,rn
  from cte where rn=1
  union all
  select cte.Columns,(case when cte.amount0 then (case when cte.amountremainingamount then cte.amount-remainingamount else 0 end)else 0 end)amount
  ,(case when cte.amount0 then (case when cte.amountremainingamount then 0 else remainingamount-cte.amount end) else 0 end)remainingamount ,cte.rn
  from  cte inner join cte2 on cte2.rn=cte.rn-1
 )
 select columns, amount from cte2
输出:

柱 数量 第一 0 第二 0 第三 1.
即使@Kazi的解决方案也是完美的,也许这是查询的简化版本,使用cols作为行数

with recursive
data as (
  select 1 as col, 0 as amount union all
  select 2,5 union all
  select 3,5
),
cte as (
  -- anchor member
  select
    col, 
    amount, 
    9 as substract
  from data
  where col = 1
  union all
  -- recursive member
  select 
    data.col,
    case when (data.amount - cte.substract) < 0 then 0 else data.amount - cte.substract end,
    case when (cte.substract - data.amount) < 0 then 0 else cte.substract - data.amount end
  from data
    join cte
      on data.col = cte.col + 1
)
select * from cte
你可以在这上面测试


这是使用纯sql解决此类查询的唯一方法,但这些查询处理大量数据的性能通常不好。

只需使用累积和:

select t.*,
       (case when 9 >= running_amount then 0
             when 9 >= running_amount - amount then running_amount - 9
             else amount
        end) as remainder
from (select t.*,
             sum(amount) over (order by column) as running_amount
      from t
     ) t;
他是一把小提琴


注意:这假设第一列实际上表示行的顺序。

对于示例数据,您的查询无疑运行良好,但如果数据中有一个额外的行,且金额为5,则您的查询将停止以执行正确的操作。@JaimeDrq。在这种情况下效果很好:。嗨@Gordon Linoff,据我所知,当9耗尽时,它应该返回0,而不是5。9是一个在每次迭代中随行而变化的值,而不是一个固定值。就我所知,这个问题。。。。你可以看到我在这方面的行为,也许你可以用一些滞后函数来完成这项工作,但我不知道mysql中是否允许使用它们,我必须承认我喜欢递归cte,它们太奇怪了@jaimerq。我想你误解了这个问题。递归CTE很棒。然而,其他方法通常具有更好的性能,因此应该明智地使用它们。