计算日期/时间部分的平均值
Posted
技术标签:
【中文标题】计算日期/时间部分的平均值【英文标题】:Computing average values over sections of date/time 【发布时间】:2010-10-30 17:53:33 【问题描述】:问题:
我有一个传感器读数数据库,其中包含读取传感器时间的时间戳。基本上是这样的:
Sensor | Timestamp | Value
现在我想用这些数据制作一个图表,并制作几个不同的图表。假设我想要一个用于最后一天,一个用于上周,一个用于最后一个月。每个图表的分辨率会有所不同,因此对于日图,分辨率将为 1 分钟。对于周图,它将是一小时,对于月图,它将是一天或四分之一天。
所以我想要一个输出是每个分辨率的平均值(例如,天 = 一分钟内的平均值,周 = 一小时内的平均值等等)
例如:
Sensor | Start | End | Average
如何在 mysql 中轻松快速地完成此操作?我怀疑它涉及创建一个临时表或排序并将传感器数据与其连接以获得传感器的平均值?但我对 mySQL 的了解充其量是有限的。
有没有真正聪明的方法来做到这一点?
【问题讨论】:
【参考方案1】:不完全是您想要的结果表,但这里是做 1 分钟解析的开始:
SELECT sensor,minute(timestamp),avg(value)
FROM table
WHERE <time period specifier limits to a single hour>
GROUP BY sensor, minute(timestamp)
【讨论】:
【参考方案2】:SELECT DAY(Timestamp), HOUR(Timestamp), MINUTE(Timestamp), AVG(value)
FROM mytable
GROUP BY
DAY(Timestamp), HOUR(Timestamp), MINUTE(Timestamp) WITH ROLLUP
WITH ROLLUP
子句在这里产生额外的行,每个 HOUR
和 DAY
的平均值是这样的:
SELECT DAY(ts), HOUR(ts), MINUTE(ts), COUNT(*)
FROM (
SELECT CAST('2009-06-02 20:00:00' AS DATETIME) AS ts
UNION ALL
SELECT CAST('2009-06-02 20:30:00' AS DATETIME) AS ts
UNION ALL
SELECT CAST('2009-06-02 21:30:00' AS DATETIME) AS ts
UNION ALL
SELECT CAST('2009-06-03 21:30:00' AS DATETIME) AS ts
) q
GROUP BY
DAY(ts), HOUR(ts), MINUTE(ts) WITH ROLLUP
2, 20, 0, 1
2、20、30、1
2、20、空、2
2、21、30、1
2、21、空、1
2,空,空,3
3、21、30、1
3、21、空、1
3、空、空、1
空,空,空,4
2, 20, NULL, 2
在这里意味着COUNT(*)
是2
用于DAY = 2
、HOUR = 20
和所有分钟。
【讨论】:
这会产生与我期望的结果接近的结果。 “WITH ROLLUP”有什么作用,因为如果我删除它似乎会产生相同的结果? 来自 MySQL 参考手册:“将 WITH ROLLUP 修饰符添加到 GROUP BY 子句会导致查询生成另一行,显示所有值的总计” 我猜我可以使用任何日期函数来进行分组,以便更容易地制作不同的图表,所以这正是我想要的。谢谢。【参考方案3】:我使用的代码与此非常相似(未经测试,但它取自工作代码)
设置变量:
$seconds = 3600;
$start = mktime(...); // say 2 hrs ago
$end = .... // 1 hour after $start
然后运行查询
SELECT MAX(`when`) AS top_When, MIN(`when`) AS low_When,
ROUND(AVG(sensor)) AS Avg_S,
(MAX(`when`) - MIN(`when`)) AS dur, /* the duration in seconds of the actual period */
((floor(UNIX_TIMESTAMP(`when`) / $seconds)) * $seconds) as Epoch
FROM `sensor_stats`
WHERE `when` >= '$start' AND `when` <= '$end' and duration=30
GROUP BY Epoch/*((floor(UNIX_TIMESTAMP(`when`) / $seconds)) * $seconds)*/
这样做的好处是您可以拥有任何您想要的时间段 - 甚至不需要将它们设置为“整数”,例如完整的时钟小时(甚至是时钟分钟,0-59)。
【讨论】:
我无法让这个查询工作:“'where 子句'中的未知列'duration'”。如果我用 dur 替换 duration 也不起作用。 在我的原始数据库中,我存储数据的持续时间(可能是 30 秒,可能是一小时,可能是一天)。由于您自己的表是时间点记录,因此您可能可以删除查询的那部分('and duration=30')。以上是关于计算日期/时间部分的平均值的主要内容,如果未能解决你的问题,请参考以下文章