FIX MYSQL 更新内部联接和按查询排序并设置变量

FIX MYSQL UPDATE INNER JOIN and ORDER BY QUERY and SET VARIABLE

我有 2 个 MYSQL 表:持续时间和任务。

CREATE TABLE `durations` (
  `task_type` varchar(10) NOT NULL,
  `seconds` int(11) NOT NULL
) ENGINE=InnoDB ;

CREATE TABLE `tasks` (
  `id` int(11) NOT NULL,
  `task_type` varchar(10) NOT NULL,
  `const` int(11) NOT NULL,
  `timestamp` int(11) NOT NULL,
  `status` int(11) NOT NULL,
  `tempCol` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB ;


task_type   seconds
type1       3
type2       5

id  task_type   const   timestamp   status  tempCol
1   type1       1       10          0       0              
2   type1       2       3           0       0
3   type1       3       12          0       0
4   type1       4       5           0       0


我有一个总时间值:例如 15 秒。从这个值开始,只有在 total_time - tasks.const*durations.seconds 是 > 0。如果连续更新,total_time 减少 tasks.const*durations.seconds 以用于下一行。 我有 运行 以下查询:

SET @tempVariable = 15;
UPDATE tasks 
INNER JOIN durations ON tasks.task_type=durations.task_type
SET status=1, tasks.tempCol = (@tempVariable:=@tempVariable-tasks.const*durations.seconds)
WHERE @tempVariable-tasks.const*durations.seconds > 0
ORDER BY tasks.timestamp ASC

我创建了 tempCol,以便可以在每一行中更新 @tempVariable。 由于 UPDATE 和 ORDER BY 的不正确使用,此查询不起作用。如果我省略 order by 子句,查询工作正常,但是,我需要按时间戳 ASC 更新值 ORDER。

有任何修复查询的建议吗?

谢谢。

已编辑。 我基于 GMB 解决方案的最终查询是:

SET @tempVariable = 15;
update tasks t
inner join (
    select t.id, (t.const * d.seconds) workload
    from tasks t
    inner join durations d on d.task_type = t.task_type
    order by t.`timestamp` asc
) t1 on t1.id = t.id
set t.status = 1, t.tempCol=(@tempVariable:=@tempVariable-t1.workload)
where @tempVariable-t1.workload >= 0

如果你是 运行 MySQL 8.0,你可以用 window 函数来做到这一点:

update tasks t
inner join (
    select t.id, sum(t.const * d.second) over(order by t.id) total_duration
    from tasks t
    inner join duration d on d.task_type = t.task_type
) t1 on t1.id = t.id
set t.status = 1
where t1.total_duration <= 15

在早期版本中,我会使用相关子查询而不是变量:

update tasks t
inner join (
    select t.id, 
        (select sum(t1.const * d.second) from tasks t1 where t1.id <= t.id) total_duration
    from tasks t
    inner join duration d on d.task_type = t.task_type
) t1 on t1.id = t.id
set t.status = 1
where t1.total_duration <) 15