有没有更好的方法来处理这种情况?
我有一张桌子,每5分钟的“时间”块有几行“速度”。我想在这些5分钟的12个区块中取平均值来获得每小时的速度。我想出的虚拟方法是计算每个5分钟块的总和,然后将它们除以12。
有没有更好的方法,无论是编码简单还是sql效率?
SELECT (
SUM(CASE WHEN time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
10 MINUTE) AND time < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
5 MINUTE) THEN speed ELSE 0 END) +
SUM(CASE WHEN time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
15 MINUTE) AND time < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
10 MINUTE) THEN speed ELSE 0 END) +
SUM(CASE WHEN time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
20 MINUTE) AND time < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
15 MINUTE) THEN speed ELSE 0 END) +
SUM(CASE WHEN time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
25 MINUTE) AND time < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
20 MINUTE) THEN speed ELSE 0 END) +
SUM(CASE WHEN time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
30 MINUTE) AND time < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
25 MINUTE) THEN speed ELSE 0 END) +
SUM(CASE WHEN time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
35 MINUTE) AND time < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
30 MINUTE) THEN speed ELSE 0 END) +
SUM(CASE WHEN time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
40 MINUTE) AND time < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
35 MINUTE) THEN speed ELSE 0 END) +
SUM(CASE WHEN time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
45 MINUTE) AND time < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
40 MINUTE) THEN speed ELSE 0 END) +
SUM(CASE WHEN time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
50 MINUTE) AND time < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
45 MINUTE) THEN speed ELSE 0 END) +
SUM(CASE WHEN time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
55 MINUTE) AND time < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
50 MINUTE) THEN speed ELSE 0 END) +
SUM(CASE WHEN time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
60 MINUTE) AND time < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
55 MINUTE) THEN speed ELSE 0 END) +
SUM(CASE WHEN time > DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
65 MINUTE) AND time < DATE_SUB(CURRENT_TIMESTAMP, INTERVAL
60 MINUTE) THEN speed ELSE 0 END)
)/12
FROM table
谢谢!
答案 0 :(得分:1)
SELECT AVG(IFNULL(ws.sums, 0))
FROM
(
SELECT 1 i union all SELECT 2 union all SELECT 3 union all SELECT 4 union all SELECT 5 union all SELECT 6 union all SELECT 7 union all SELECT 8 union all SELECT 9 union all SELECT 10 union all SELECT 11 union all SELECT 12
) windows
LEFT JOIN
(
SELECT SUM(speed) sums,
FLOOR(TIME_TO_SEC(TIMEDIFF(CURRENT_TIMESTAMP, time)) / 300) window
FROM workers_speeds
WHERE TIME_TO_SEC(TIMEDIFF(CURRENT_TIMESTAMP, time)) / 60 < 65
AND TIME_TO_SEC(TIMEDIFF(CURRENT_TIMESTAMP, time)) / 60 > 5
GROUP BY FLOOR(TIME_TO_SEC(TIMEDIFF(CURRENT_TIMESTAMP, time)) / 300)
) ws on windows.i = ws.window
Click here to see it in action at SQL Fiddle
说明的
首先查看底部内部查询...我们需要一种识别每个间隔的简单方法。为此,我使用TIMEDIFF()
函数来获取time
列与当前时间之间的差异。这是以h:m:s格式返回的,因此我将其传递给TIME_TO_SEC()
以转换为秒。我们现在可以除以300(5分钟内的秒数)并使用FLOOR()
函数向下舍入到最接近的整数。这为我们提供了每种5分钟间隔的ID,范围从1到12,我们可以用GROUP BY
。然后,我们会在SELECT
中添加此ID,并为其添加别名window
并添加WHERE
&amp; AND
条款确保我们仅包含1小时的数据,忽略最近的5分钟。
现在查看外部查询...我生成一个派生表windows
,其中包含12行虚拟数据,只是整数1到12.我们可以LEFT OUTER JOIN
内部查询也作为派生表ws
,它允许我们确保总共返回12行。如果区间不包含任何数据,ws.sums
将为null,但我们可以使用IFNULL()
将其转换为0。
我不完全确定它会按照您的要求行事,所以如果您使用它,您应该确保进行必要的测试,特别是在间隔的边界上。