Uma função de janela com uma função de janela personalizada moldura torna isso incrivelmente simples :
SELECT ts
,avg(val) OVER (ORDER BY ts
ROWS BETWEEN CURRENT ROW AND 7 FOLLOWING) AS avg_8h
FROM tbl;
Demonstração ao vivo no sqlfiddle.
O quadro para cada média é a linha atual mais as 7 seguintes. Isso pressupõe que você tenha exatamente uma linha para cada hora. Seus dados de amostra parecem implicar isso, mas você não especificou.
Do jeito que está,
avg_8h
para a final (de acordo com ts
) 7 linhas do conjunto são computadas com menos linhas, até que o valor da última linha seja igual à sua própria média. Você não especificou como lidar com o caso especial.