我早上已经问了这个问题,但没有得到任何答案。所以我删除了之前的一个,并再次问这个因为我被困了很长一段时间。希望你们能帮助我。
我有一个名为overtime
的表格如下:
| total | remain | t_date |
|-------|--------|---------------------|
| 3 | 0 | 2016-01-01 12:20:00 |
| 4 | 0 | 2016-02-01 13:10:00 |
| 2 | 0 | 2016-03-01 14:40:00 |
| 3 | 0 | 2016-04-01 10:20:00 |
| 5 | 2 | 2016-05-01 17:20:00 |
我想更新列保留order by t_date desc
,我也有一个输入参数,假设它是$ h = 9,预期结果是:
| total | remain | t_date |
|-------|--------|---------------------|
| 5 | 5 | 2016-05-01 17:20:00 | -- remain will be updated to 5 cause total = 5, then $h(6) = $h(9) - (total(5) - remain(2))
| 3 | 3 | 2016-04-01 10:20:00 | -- remain will be updated to 3 cause total = 3, then $h(3) = $h(6) - (total(3) - remain(0))
| 2 | 2 | 2016-03-01 14:40:00 | -- remain will be updated to 2 cause total = 2, then $h(1) = $h(3) - (total(2) - remain(0))
| 4 | 1 | 2016-02-01 13:10:00 | -- remain will be updated to 1 cause $h only has 1, then $h will be 0
| 3 | 0 | 2016-01-01 12:20:00 | -- cause $h = 0, this row has no need to be updated
编辑:
示例数据如上所述,我想要做的是更新列remain
,remain
'值基于总和输入参数(假设它是9):
order by t_date desc
。例如,我必须首先更新2016-05-01 17:20:00
行,然后更新2016-04-01 10:20:00
,然后更新2016-03-01 14:40:00
等等...... remain
应更新为total
的值。例如,第一行2016-05-01 17:20:00
,total
= 5且remain
= 2,因此remain
将更新为5,参数将减去total
- remain
,它将是6并执行下一行的分配,直到行2016-02-01 13:10:00
,参数为1,因此此行remain
只需要更新1.另一行不需要更新。 Here is SQLFiddle demo。
如果有任何不明确的问题,请发表评论,我可以解释一下。
感谢任何帮助。提前谢谢。
答案 0 :(得分:1)
您可以使用使用变量 @h 进行计算的子查询:
update overtime
join (select t_date,
least(@h,total)
+ if(least(@h,total) + remain <= total, remain, 0) new_remain,
@h := greatest(0, @h - (total - remain)) h
from overtime,
(select @h := 9) init
order by t_date desc
) as calc
on overtime.t_date = calc.t_date
set overtime.remain := calc.new_remain;
请参阅此SQL fiddle
答案 1 :(得分:1)
SELECT QUERY:
SELECT
*,
IF(
(IF(@h <= 0,0,IF(@h >= total,total, @h)) + remain) <= total,
(IF(@h <= 0,0,IF(@h >= total,total, @h)) + remain),
(IF(@h <= 0,0,IF(@h >= total,total, @h)))
) allocated,
@h := @h - (total - remain)
FROM overtime
CROSS JOIN (SELECT @h := 9) var
ORDER BY t_date DESC
更新查询:
UPDATE
overtime OT
INNER JOIN
(
SELECT
*,
IF(
(IF(@h <= 0,0,IF(@h >= total,total, @h)) + remain) <= total,
(IF(@h <= 0,0,IF(@h >= total,total, @h)) + remain),
(IF(@h <= 0,0,IF(@h >= total,total, @h)))
) allocated,
@h := @h - (total - remain)
FROM overtime
CROSS JOIN (SELECT @h := 9) var
ORDER BY t_date DESC
) AS t
ON OT.t_date = t.t_date
SET OT.remain = t.allocated;
Demo显示按上述update
查询更新后按日期降序排序的表格数据。
更多强>
答案 2 :(得分:1)
您必须使用子查询执行此操作,如下所示:
update overtime t1
join (
select overtime.*,
total - remain, IF(@h > (total - remain), total, @h + remain) as h,
@h := IF(@h > (total - remain), @h - (total - remain), 0)
from overtime
cross join (
select @h := 9
) t
order by t_date desc
) t2 on t1.t_date = t2.t_date
set t1.remain = t2.h;