我有一个包含两列的表“ my_table”
1. Timestamp (ts)
2. Value (val)
我需要为每个时间戳返回时间戳上或时间戳之前出现的10个最新值的平均值。
我可以对以下查询执行类似的操作:
SELECT t2.ts as time,
AVG(t1.val) as avg_val
FROM table_name as t1, table_name as t2
WHERE t1.ts <= t2.ts
这将返回一个时间戳以及该时间戳上或该时间戳之前出现的所有值的平均值。我需要修改此查询以返回10个最新值的平均值,而不是所有值的平均值。
PS:为一个不好的问题标题表示歉意。不确定如何构架。
答案 0 :(得分:2)
忽略先前的答案。您可以使用“穷人排名”来对按时间戳排序的行进行排名。您可以单独加入结果以查找每个等级的前9行:
SELECT a.ts, AVG(c.val)
FROM (
SELECT t1.ts, COUNT(t2.ts) AS rank
FROM t AS t1
INNER JOIN t AS t2 ON t2.ts <= t1.ts
GROUP BY t1.ts
) AS a
INNER JOIN (
SELECT t1.ts, COUNT(t2.ts) AS rank
FROM t AS t1
INNER JOIN t AS t2 ON t2.ts <= t1.ts
GROUP BY t1.ts
) AS b ON b.rank BETWEEN a.rank - 9 AND a.rank
INNER JOIN t AS c ON b.ts = c.ts
GROUP BY a.ts
我知道这有点笨拙,但是在某些情况下,它可能比关联子查询更好。
答案 1 :(得分:0)
在版本8之前的MySQL中,没有一种简单的方法可以表达此查询-即使使用变量也是如此。我不会保证性能,但这应该可以满足您的要求:
SELECT t1.ts, t1.val, AVG(t2.val)
FROM t t1 LEFT JOIN
t t2
ON t2.ts <= t.ts AND
t2.ts >= (SELECT t3.ts
FROM t t3
WHERE t3.ts <= t1.ts
ORDER BY t3.ts DESC
LIMIT 9, 1
)
GROUP BY t1.ts, t1.val;
当然,在8岁以上的人群中,这很简单:
select t.*,
avg(t.val) over (order by ts rows between 9 preceding and current row) as avg_10
from t;