2017-01-27 2 views
1

Ich habe die Tabelle wie untengleitender Mittelwert in mysql

id timestamp speed 
1 11:00:01 100 
2 11:05:01 110 
3 11:10:01 90 
4 11:15 :01 80 

Ich brauche zu berechnen Durchschnitt bewegen wie unter

id timestamp speed average 
1 11:00:01 100 100 
2 11:05:01 110 105 
3 11:10:01 90 100 
4 11:15:01 80 95 

Was habe ich versucht,

SELECT 
*, 
(select avg(speed) from tbl t where tbl.timestamp<=t.timestamp) as avg 
FROM 
tbl 

Zuerst es recht schaut leicht, aber wenn die Daten auf dem Tisch anschwellen, ist es zu langsam

Jeder schnellere Ansatz?

+0

Ist das Zeitdelta immer konstant? Es ist nicht korrekt, 'avg' zu verwenden, wenn nicht. –

Antwort

4

Ihre Anfrage ist eine Möglichkeit, ein gleitender Mittelwert zu tun:

SELECT t.*, 
     (select avg(speed) from tbl tt where tt.timestamp <= t.timestamp) as avg 
FROM tbl t; 

Die Alternative ist, um Variablen zu verwenden:

select t.*, (sum_speed/cnt) as running_avg_speed 
from (select t.*, (@rn := @rn + 1) as cnt, (@s := @s + speed) as sum_speed 
     from tbl t cross join 
      (select @rn := 0, @s := 0) params 
     order by timestamp 
    ) t; 

Ein Index für tbl(timestamp) sollte die Leistung weiter verbessern.

0

Unterstützt MySQL Fensterfunktionen?

select 
    id, timestamp, speed, 
    avg (speed) over (order by timestamp) as average 
from tbl 

Wenn es nicht dies funktionieren könnte, obwohl ich es effizient Zweifel:

select 
    min (t1.id) as id, t1.timestamp, min (t1.speed) as speed, 
    avg (t2.speed) 
from 
    tbl t1 
    join tbl t2 on 
    t2.id <= t1.id 
group by 
    t1.timestamp 
order by 
    t1.timestamp 
+0

Ja, es funktioniert gut für gegebene Daten, aber für diese Zeitstempel muss in inkrementeller Reihenfolge als ID sein. – Susang

+0

Aah, ich verstehe. Ich habe dann die gruppierte Spalte in den Zeitstempel geändert - vielleicht wird es das tun. – Hambone

+1

MySQL unterstützt keine Fensterfunktionen, daher ist die Antwort nicht korrekt. –

0

oder fein säuberlich zwischen GL zwei Antworten (performancewise sowieso) ...

SELECT x.*, AVG(y.speed) avg 
    FROM my_table x 
    JOIN my_table y 
    ON y.id <= x.id 
GROUP 
    BY x.id; 
0

Was ist eine einfache gleichzeitige Lösung Stoßen?

SET @summ=0; SET @counter=0;SELECT *,(@counter := @counter +1) as cnt, (@summ := @summ+speed) as spd, (@summ/@counter) AS avg FROM tbl; 
Verwandte Themen