So let's say that I want to keep track of my CPU temperature, with simple columns 'date' and 'temperature'. I'd like to see what period saw the highest temperatures on average in the last week. I capture the data every 10 minutes, so I want each 10 minute block averaged with the same block from the other days of the week.
So for example:
2018-01-08 02:00:00 78.3
2018-01-08 03:00:00 81.2
2018-01-09 02:00:00 74.1
2018-01-09 03:00:00 75.9
I would want the averages of each day # 02:00:00, each day # 03:00:00, and so on. (except the real data is every 10 minutes) The exact datetime varies - it's not always 02:00:02, sometimes it could be 02:00:07, etc., so I can't just do an exact conditional.
Any idea how I'd go about making this data? I assume there's some way I can use GROUP BY for this, but I'm lost as to how.
Format just the hour and minute, and group by that.
SELECT DATE_FORMAT(date, '%H:%i') AS time, AVG(temperature) AS temp
FROM yourTable
GROUP BY time
This assumes that the readings are never delayed by more than a minute from the expected 10-minute periods -- if the reading for 02:10 happens at 02:11:01 it will not be put in the group.
Related
I have a monthly offering that gives customers 30 minutes of use every month and I need to tally up their usage and group it by month, but not sure the best way to handle that since the start date could be any day of the month.
Should I prorate? Convert into full months or count the days?
Is there an ideal way to tally this? Let's say each month they get 30 minutes of use time, so I want to tally how many minutes were used that "month."
Say there is a minutes used table and the start date for the subscription is 2019-06-13 00:00:00
minutes_used_table:
Userid MinutesUsed Date
1 5 2019-06-19
1 6 2019-06-23
1 8 2019-06-28
1 15 2019-07-05
1 3 2019-07-12
1 8 2019-07-19
1 5 2019-08-14
1 3 2019-08-22
1 1 2019-08-26
1 2 2019-09-13
Or, should I prorate it and instead of tracking in 30 day increments, if they start on the 13th of June, should I just count the days from the start date to the end of the month, whatever day that is and then the days from the first of the month until the start date?
Wondering what makes the most sense and how to carry it out?
Use
GROUP BY DATEDIFF(`Date`, #starting_date) DIV #period_length
In your particular case it will be
GROUP BY DATEDIFF(`Date`, '2019-06-13 00:00:00') DIV 30
From coding point of view it's not a big deal to find first date for user, subtract it from dates and count number of 30-days periods.
But this will be very hard to support in future and this solution will have a number of corner cases: for example someone first start to use product at 20 January, after month of usage have been idle for a while and came back in April, 5. What will be right start date for that case?
So I suggest to use calendar months. And may be reduce limit on first month accordingly to the number of days left or give full trial period even on first month as user has ability to spend 30 minutes.
My DB in UTC timezone and data inserting in UTC time. I want to sum all values and group by hourly for IST time data. like below,
id data_id value serverTime
1 2 100 2016-05-02 18:30:54
2 2 100 2016-05-02 18:45:54
4 2 200 2016-05-02 19:00:54
5 2 100 2016-05-02 19:15:54
6 2 100 2016-05-02 19:30:54
7 2 100 2016-05-02 19:40:54
Query
select sum(value) as value, serverTime as date
from Data_table
where data_id=2
and serverTime between CONVERT_TZ('2016-05-03 00:00:01','+00:00', '-05:30')
and CONVERT_TZ('2016-05-03 10:45:24','+00:00', '-05:30')
group by year(date),month(date),week(date),day(date),hour(date);
above query giving result is :
200
500
But Expecting output :
600
100
because IST 12 AM = UTC- 05:30 which means 18:30 to 19:30 but here my query calculating only 18:30 to 19:00, 19:00 to 20:00, 20:00 to 21:00 which is not accuracy value.
I want to calculate value for 18:30 to 19:30 and 19:30 to 20:30 for accuracy value for IST time data.
How to solve this?
By IST, I assume you mean India Standard Time, which is 5 hours and 30 minutes ahead of UTC. As a fixed offset, that would be +05:30, not -05:30. You're results are incorrect because you have the sign inverted.
The CONVERT_TZ function accepts any of:
'SYSTEM' for the local system time zone
Fixed offsets in standard ISO 8601 format, which have positive offsets East of UTC, such as '+05:30' for India, or '-10:00' for Hawaii.
Named time zones, using standard IANA/Olson TZDB identifiers, assuming the time zone tables are populated. India's is 'Asia/Kolkata', US Eastern time is 'America/New_York', etc. Using this option requires the mysql time zone tables to be populated, per the documentation.
In general, named time zones are preferred because they accommodate changes in offset due to daylight saving time and historical changes. However, India has been fixed at +05:30 since 1942 and isn't likely to change in the near future, so it's reasonable to use the fixed offset approach if this is the only time zone you need to deal with.
Also note that "IST", like many time zone abbreviations, is ambiguous. It can mean India Standard Time (+05:30), Ireland Standard Time (+01:00) or Israel Standard Time (+02:00). Also note that Ireland Standard Time is actually a daylight time zone offset, despite having the name "Standard" in it. To avoid confusion, please specify your particular location when referring to IST in the future, and don't ever expect a computer to be able to distinguish them.
You should convert also date in group by
select sum(value) as value , hour(CONVERT_TZ(serverTime, '+00:00', '-05:30')) as hour
from Data_table
where data_id=2
and serverTime between CONVERT_TZ('2016-05-03 00:00:01','+00:00', '-05:30')
and CONVERT_TZ('2016-05-03 10:45:24','+00:00', '-05:30')
group hour(CONVERT_TZ(serverTime, '+00:00', '-05:30'));
Test for between condition
select CONVERT_TZ('2016-05-03 00:00:01','+00:00', '-05:30') ,
CONVERT_TZ('2016-05-03 10:45:24','+00:00', '-05:30') from dual;
select CONVERT_TZ('2016-05-03 00:00:01','+00:00', '-05:30') ,
CONVERT_TZ('2016-06-03 01:00:24','+00:00', '-05:30') from dual;
I have statistical data like this:
time val1
1424166578 51
1424166877 55
1424167178 57
1424167477 57
time is a unix timestamp. There is one record every 5 minutes excluding nights and sundays. This continues over several weeks.
Now I want to get these values for an average day and an average week. The result should include values for every 5 minutes like normal but for average past days or weeks.
The result should look like this:
time val1
0 43.423
300 46.635
600 51.887
...
So time could be a timestamp with relative time since day or week start. Perhaps it is better to use DATETIME... not sure.
If I use GROUP BY FROM_UNIXTIME(time, '%Y%m%d') for example I get one value for the whole day. But I want all average values for all days.
You seem to be interested in grouping dates by five minute intervals instead of dates. This is fairly straightforward:
SELECT
HOUR(FROM_UNIXTIME(time)) AS HH,
(MINUTE(FROM_UNIXTIME(time)) DIV 5) * 5 AS MM,
AVG(val1) AS VAL
FROM your_table
WHERE time > UNIX_TIMESTAMP(CURRENT_TIMESTAMP - INTERVAL 7 DAY)
GROUP BY HH, MM
The following result will explain how date is clamped:
time FROM_UNIXTIME(time) HH MM
1424166578 2015-02-17 14:49:38 14 45
1424166877 2015-02-17 14:54:37 14 50
1424167178 2015-02-17 14:59:38 14 55
1424167477 2015-02-17 15:04:37 15 00
I would approach this as:
select date(from_unixtime(time)) as day, avg(val)
from table t
group by date(from_unixtime(time))
order by day;
Although you can use the format argument, I think of that more for converting the value to a string than to a date/time.
I am creating a REST API for a booking calendar, and right now I am trying to figure out the most efficient way of writing a query that returns all timestamps between two dates with a 15 minute interval. If I supply2013-09-21 and 2013-09-22 I would like to get:
2013-09-21 00:15:00
2013-09-21 00:30:00
2013-09-21 00:45:00
2013-09-21 01:00:00
2013-09-21 01:15:00
2013-09-21 01:30:00
...
2013-09-22 23:15:00
2013-09-22 23:30:00
2013-09-22 23:45:00
I would then use this query as a subquery and apply some conditions on it to remove timeslots outside working hours (which are not constant), booked timeslots, etc.
I have seen a lot of blog posts where the author creates a "calendar table" which stores all these timestamps, but that seems like a waste to me since that data doesn't need to be stored.
Any suggestions on how I could do this or a better way to fetch/store the data?
Here is a process that generates 95 rows incrementing a date variable as it goes and then left join the table with the dated entries to the "solid" table that has generated dated rows.
select str_to_date('2010-01-01', '%Y-%m-%d') into #ad;
select * from
(select (#ad := date_add(#ad, INTERVAL 15 MINUTE)) as solid_date from wp_posts limit 95) solid
left join
wp_posts
on solid.solid_date = post_date
I've no idea how to generate an arbitrary number of rows in mysql so i'm just selecting from a table with more than 95 rows (24 hours * 4 appointments per hour less one at midnight) -- my wordpress posts table. Nothing stopping you making just such a table and having a single column with a single incrementing integer in if there are no better ways to do it (i'm an oracle guru not a mysql one). Maybe there isn't one: How do I make a row generator in MySQL?
Where you see wp_posts, substitute the name of your appointments table. Where you see the date, substitute your start date.
The query above produces a list of dates starting 15 after midnight on the chosen day (in my example 2010-01-01)
You can add a WHERE appointments.primary_key_column_here IS NULL if you want to find free slots only
Note you didn't include midnight in your spec. If you want midnight on the first day, start the date in the variable 15 minutes before and limit yourself to 96 rows. If you want midnight on the end day, just limit yourself to 96 rows
I am trying to display data associated with date. However in my case, I don't want the date to start at 00:00:00 and finishes at 23:59:59. Rather I want it to start at 16:00:00 and finishes at 06:00:00 the next day. In other words I want to create a custom time for date.
In the same time I want to GROUP_BY date.
For instance I have these values in the database:
want it to give me:
date: 2013-09-08 count: 2
date: 2013-09-09 count: 1
I am not asking for code, but a way to think about it, or useful methods.
Thank you in advance!
The simplest method is to take the existing date and subtract six hours to get the "effective" date. You would do this for output purposes only.
Example:
select date(datecol - interval 6 hour) as MyDate, count(*)
from t
group by date(datecol - interval 6 hour);
You can use a where clause to remove the times between 6:00 and 16:00 (unless that is a typo).