Reputation: 141
I'm working on candlestick chart data. I have a database table (MySql) with
created value
2017-09-25 17:55:04 3322.09
2017-09-25 18:00:03 3317.49
2017-09-25 18:05:02 3316.12
2017-09-25 18:10:03 3325.16
2017-09-25 18:15:04 3326.01
2017-09-25 18:20:03 3330.49
2017-09-25 18:25:04 3331.49
2017-09-25 18:30:04 3335.24
2017-09-25 18:35:03 3347.13
2017-09-25 18:40:03 3343.21
2017-09-25 18:45:05 3341.78
2017-09-25 18:50:03 3339.64
2017-09-25 18:55:04 3336.12
2017-09-25 19:00:04 3327.73
2017-09-25 19:05:03 3327.96
2017-09-25 19:10:04 3325.93
And I'm trying to select a maximum, minimum, open value, close value for any period of time (e.g. 15 minutes or every 4 hours, every 6 days etc.)
So far I have
SELECT p.created, HOUR(`DATE`), MAX(p.value), MIN(p.value)
FROM price
GROUP BY DATE(`DATE`),HOUR(`DATE`)
Not so complicated. It gives me maximum and minimum from every hour, so for minutes and "full" periods like days, weeks, month I can use MONTH, DAY etc. functions.
Any idea how to build a query for any period of time, let's say 28 minutes or 31 hours etc? Also, this works for maximum and minimum, but I also need a opening value (first) for time period and close value (last).
Upvotes: 0
Views: 2829
Reputation: 125865
To group on arbitrary periods of time, you can take the UNIX time value of your created
column (i.e. the number of seconds since the UNIX epoch) and divide by the size of your desired periods, taking only the integer part of the resulting quotient (and discarding the remainder). So, to group every 28 minutes:
SELECT FROM_UNIXTIME(28*60 * (UNIX_TIMESTAMP(created) DIV (28*60))) grp_id
MIN(value) min_value,
MAX(value) max_value,
MIN(created) min_created,
MAX(created) max_created
FROM price
GROUP BY grp_id
You'll notice that I've also selected the min_created
and max_created
, which yield the times of the first and last values in each group. You can then join the result back to the price
table again to obtain the value
s of the relevant records (this is essentially an instance of the "groupwise maximum/minimum" problem):
SELECT t.grp_id,
t.min_value,
t.max_value,
price_min.value first_value,
price_max.value last_value
FROM (
SELECT FROM_UNIXTIME(28*60 * (UNIX_TIMESTAMP(created) DIV (28*60))) grp_id
MIN(value) min_value,
MAX(value) max_value,
MIN(created) min_created,
MAX(created) max_created
FROM price
GROUP BY grp_id
) t JOIN price price_min ON price_min.created = t.min_created
JOIN price price_max ON price_max.created = t.max_created
See it on sqlfiddle.
Upvotes: 4