0

我有一个小的时间跟踪网络应用程序(在 Rails 3.2.8 和 MySQL 中实现)。该应用程序有几个用户在给定日期将时间添加到特定任务中。系统设置为每个日期每个任务用户只能有 1 个时间条目(即行)。即,如果您在同一任务和日期上添加两次时间,它将向现有行添加时间,而不是创建新行。user_id/task_id/date唯一性由索引强制执行UNIQUE

现在我正在寻找合并 2 个任务。用最简单的术语来说,将任务 ID 2 合并到任务 ID 1 将采用此

time  | user_id  | task_id  | date
------+----------+----------+-----------
10    | 1        | 1        | 2012-10-29
15    | 2        | 1        | 2012-10-29
10    | 1        | 2        | 2012-10-29
5     | 3        | 2        | 2012-10-29

并将其更改为

time  | user_id  | task_id  | date
------+----------+----------+-----------
20    | 1        | 1        | 2012-10-29 <-- time values merged (summed)
15    | 2        | 1        | 2012-10-29 <-- no change
5     | 3        | 1        | 2012-10-29 <-- task_id changed (no merging necessary)

即通过对时间值求和来合并,其中给定的 user_id/date/task 组合会发生冲突。

ON DUPLICATE KEY UPDATE ...我想如果我为每个 task_id=2 条目进行插入,我可以使用唯一约束来执行。但这似乎很不雅。

我还试图找到一种方法,首先使用汇总时间更新任务 1 中的所有行,但我无法完全弄清楚这一点。

有任何想法吗?


更新:离开奥拉夫的回答,我想出了这个,这似乎正在工作

INSERT INTO `timetable`
(`time`, `user_id`, `task_id`, `date`)
(
    SELECT
      SUM(`time`) AS `time`,
      `user_id`,
      1 AS `task_id`,
      `date`
    FROM `timetable` AS `t1`
    WHERE `task_id` IN (1,2)
    GROUP BY `user_id`, `date`
)
ON DUPLICATE KEY UPDATE `time`=VALUES(`time`);

DELETE FROM `timetable` WHERE `task_id`=2;

如果有人有更好的解决方案(或者我的解决方案中有任何我应该知道的问题),我会留下这个问题

更新2:不知道为什么我之前没有意识到这一点,但是我的解决方案可能会做很多多余的INSERT,因为它还会找到所有只存在于目标任务中并且不需要合并的条目。在上面的示例数据中,将找到第二行,重新插入,触发重复键,并将时间设置为与现在相同。因此,如果目标任务有 10 行,源任务有 0 行,它仍然会执行 10 次(完全没有意义的)INSERT。

这可以通过将内部 SELECT 的所有内容包装在另一个 SELECT 中来避免,并用于COUNT(*)仅查找需要合并的那些行。当然,这将需要另一个更多的查询来更新那些不需要合并的行的 task_id 据我所知,这需要一个连接来弄清楚)。

4

1 回答 1

0

总结user_iddate将是:

select sum(time), user_id, 1, date
from timetable
group by user_id, date;

更新时间表(感谢@Flambino):

insert into timetable (time, user_id, task_id, date)
    select sum(time), user_id, 1, date
    from timetable
    group by user_id, date
on duplicate key update time = values(time);

最后删除所有task_id非 1 的行:

delete from timetable where task_id > 1;

当更新仅限于任务 1 和 2 时,像 @Flambino 的更新一样应用 where 子句。

于 2012-10-29T16:52:20.590 回答