首页 > 解决方案 > 每周更新 MYSQL 字段的最佳方法?

问题描述

我想每周更新 MySQL 表“Persons”中的一个字段,其中包含“Tasks”表的两个字段 end_date 和 start_date 的平均值:

PERSON:
+----------------+-------------+------+-----+---------+-------+
| Field          | Type        | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| average_speed  | int(11)     | NO   |     | 0       |       |
+----------------+-------------+------+-----+---------+-------+

TASKS:
+----------------+-------------+------+-----+---------+-------+
| Field          | Type        | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| person_id      | int(11)     | NO   |     | NULL    |       |
| start_date     | date        | NO   |     | NULL    |       |
| end_date       | date        | NO   |     | NULL    |       |
+----------------+-------------+------+-----+---------+-------+

(表格不完整)。

average_speed = AVG(task.end_date - task.start_date)

现在,Tasks 表真的很大,并且**我不想计算每个人每周每个任务的平均值**。(这是一个解决方案,但我试图避免它)。

更新平均速度的最佳方法是什么?我考虑在人员表中添加两列:

因此,在新的更新中,我可以执行类似 average_speed = (last_sum+new_sum) / (last_count + new_count) 的操作,其中 new_count 是上周任务的总和。

有更好的解决方案/架构吗?

编辑:回答评论,我会做的查询是这样的:

SELECT 
    count(t.id) as last_count,
    sum(TIMESTAMPDIFF(MINUTE, t.start_date, t.end_date)) as last_sum
    avg(TIMESTAMPDIFF(MINUTE, t.start_date, t.end_date))
from tasks as t
where t.end_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 1 WEEK) AND CURDATE()

我可以依靠 php 脚本来获取结果并进行一些计算

标签: mysqlarchitectureaverage

解决方案


由于您上面列出的所有原因以及其他原因,定期更新表是一种不好的方法。

如果您有权访问写入 Tasks 表的代码,那么这是放置更新的最佳位置。添加一个Average字段并在编写任务结束时间时计算并设置该值。

如果您无权访问代码,您可以在表中添加一个计算字段来显示平均值,并让 SQL 在执行查询期间计算出来。这可能会稍微减慢查询速度,但数据始终有效,并且 SQL 足够智能,仅在需要时才计算该值。

第三个(丑陋的)选项是表上的触发器,它会在适当的时候更新值。我不喜欢触发器,因为它们将业务逻辑隐藏在意想不到的地方,但有时你只需要完成工作。


推荐阅读