Reputation: 739
I have the following table:
╔════════════╦══════════╦═══════╦══════╗
║ DATE ║ TIME ║ Price ║ Avg ║
╠════════════╬══════════╬═══════╬══════╣
║ 01/01/2000 ║ 00:00:00 ║ 1 ║ ║
║ 01/01/2000 ║ 00:05:00 ║ 2 ║ ║
║ 01/01/2000 ║ 00:10:00 ║ 3 ║ ║
║ 01/01/2000 ║ 00:15:00 ║ 4 ║ ║
║ 01/01/2000 ║ 00:20:00 ║ 5 ║ ║
║ 01/01/2000 ║ 00:25:00 ║ 6 ║ ║
║ 01/01/2000 ║ 00:30:00 ║ 7 ║ ║
║ 01/01/2000 ║ 00:35:00 ║ 8 ║ ║
║ 01/01/2000 ║ 00:40:00 ║ 9 ║ ║
║ 01/01/2000 ║ 00:45:00 ║ 10 ║ ║
║ 01/01/2000 ║ 00:50:00 ║ 11 ║ ║
║ 01/01/2000 ║ 00:55:00 ║ 12 ║ ║
║ 01/01/2000 ║ 01:00:00 ║ 13 ║ ║
╚════════════╩══════════╩═══════╩══════╝
And I want to fill the column Avg with a moving average of price of the last 15 minutes (not including the last average), so that the outcome is:
╔════╦════════════╦══════════╦═══════╦══════╗
║ ID ║ DATE ║ TIME ║ Price ║ Avg ║
╠════╬════════════╬══════════╬═══════╬══════╣
║ 1 ║ 01/01/2000 ║ 00:00:00 ║ 10 ║ 10 ║
║ 2 ║ 01/01/2000 ║ 00:05:00 ║ 2 ║ ║
║ 3 ║ 01/01/2000 ║ 00:10:00 ║ 6 ║ ║
║ 4 ║ 01/01/2000 ║ 00:15:00 ║ 4 ║ 4 ║ <-- Average of 2,6,4
║ 5 ║ 01/01/2000 ║ 00:20:00 ║ 7 ║ ║
║ 6 ║ 01/01/2000 ║ 00:25:00 ║ 6 ║ ║
║ 7 ║ 01/01/2000 ║ 00:30:00 ║ 5 ║ 6 ║ <-- Average of 7,6,5
║ 8 ║ 01/01/2000 ║ 00:35:00 ║ 2 ║ ║
║ 9 ║ 01/01/2000 ║ 00:40:00 ║ 2 ║ ║
║ 10 ║ 01/01/2000 ║ 00:45:00 ║ 2 ║ 2 ║ <-- Average of 2,2,2
║ 11 ║ 01/01/2000 ║ 00:50:00 ║ 10 ║ ║
║ 12 ║ 01/01/2000 ║ 00:55:00 ║ 12 ║ ║
║ 13 ║ 01/01/2000 ║ 01:00:00 ║ 2 ║ 8 ║ <-- Average of 10,12,2
╚════╩════════════╩══════════╩═══════╩══════╝
NOTE: While there is ALWAYS an entry every 5 minutes, there could be additional entries in between(i.e.: There could be a price at 00:32:00).
What I have right now is the following:
UPDATE table AS t
INNER JOIN
(SELECT AVG(Price) as average,
floor((unix_timestamp(CONCAT(date, ' ', time)))/900 ) as timekey
FROM table
GROUP BY timekey ) t1
ON t.ID = t1.ID
SET 15_MIN_AVERAGE = t1.average
But this seems to group the entries that are on the 15 minutes and the next ones, instead of the previous ones like I want.
Any help is greatly appreciated.
Thanks!
Upvotes: 1
Views: 2349
Reputation: 1271231
You can do what you want with a correlated subquery:
select t.*,
(select avg(t2.price)
from table t2
where t2.time <= t.time and t2.time >= date_sub(t.time, interval 15 minute)
) as avgprice
from table t;
You can then do tbe update that you want, using this in a join
:
update table t join
(select t.*,
(select avg(t2.price)
from table t2
where t2.time <= t.time and t2.time >= date_sub(t.time, interval 15 minute)
) as avgprice
from table t
) tt
on t.id = tt.id
set t.15_MIN_AVERAGE = ttavgprice
where minute(t.time) in (0, 15, 30, 45);
Upvotes: 4