Display times in 5 minute intervals in database - mysql

We've got a big database which registers positions of tracked vehicles. So, every second, we have thousands of positions coming.
The aim is to filter the SQL request, because we have too many datas. If I do a simple "select time from positions", i'll get a lot of position times. But i'm not interested in all of them.
So my idea was to create an interval. I want the database to give me the position time every 5 minutes.
The database uses STR_TO_DATE function to get position time.
My data is like this :
2019-06-05 00:00:00
2019-06-05 00:01:00
2019-06-05 00:01:00
2019-06-05 00:02:00
And i want this :
2019-06-05 00:00:00
2019-06-05 00:05:00
2019-06-05 00:10:00
2019-06-05 00:15:00
As you see here, the position times "01" "02" .. have disappeared. Because i don't want them. I want the position time in 00:05:00 , then in 00:10:00 , BUT I don't want the position time between these intervalls.
select
distinct time
from
positions
where
time>STR_TO_DATE('05/06/2019 00:00', '%d/%m/%Y %H:%i')
and time<STR_TO_DATE('06/06/2019 00:00', '%d/%m/%Y %H:%i')
limit 1000;
How can I do this in my case please? How can I change my code ?
I'm using Mysql workbench version 6.3.

Supposing the time is of type DATETIME or TIMESTAMP and that you want only the records where the seconds within the time equal 0 and the minutes within that time are a multiple of 5, you may try the following:
WHERE MOD(UNIX_TIMESTAMP(time), 300) = 0
I'm not sure whether this is correct since I don't know how this function behaves with respect to leap seconds. I cannot test this in my environment.
In order to resolve this, you may try this:
WHERE MOD(EXTRACT(MINUTE FROM time), 5) = 0
AND EXTRACT(SECOND FROM time) = 0 -- if relevant
AND EXTRACT(MICROSECOND FROM time) = 0

Related

Group by average intervals across a timeframe

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.

MySQL: How to convert seconds to mm:ss format?

I want to convert seconds to minute : seconds format in sql select statement.
At the moment I am using:
SELECT SEC_TO_TIME(duration) from messages;
It works perfectly but it gives me this format of time: hh:mm:ss
but I need mm:ss
Is it possible to convert seconds into mm:ss format using sql query?
If the value is less than an hour, then just do:
SELECT RIGHT(SEC_TO_TIME(duration), 5) from messages;
If you might go over an hour, then do the arithmetic:
SELECT CONCAT_WS(':', FLOOR(SEC_TO_TIME(duration) / 60),
SEC_TO_TIME(duration) % 60)
I recently had a similar project where I needed to convert stored seconds to m:ss format. No matter the amount, there needed to be at least one digit representing minutes and two digits representing seconds. The hours placeholder was forbidden, so the minutes value could acceptably go beyond 59 and also contain more than 2 digits. The minute value must not be zero-padded.
This is what I used: (SQLFiddle Demo)
CONCAT(FLOOR(seconds/60), ':', LPAD(MOD(seconds,60), 2, 0)) AS `m:ss`
aka
CONCAT(FLOOR(seconds/60), ':', LPAD(seconds%60, 2, 0)) AS `m:ss`
seconds | m:ss
-----------------
0 | 0:00
1 | 0:01
10 | 0:10
60 | 1:00
61 | 1:01
71 | 1:11
3599 | 59:59
3600 | 60:00
5999 | 99:59
6000 | 100:00
TIME_FORMAT(SEC_TO_TIME(seconds),'%i:%s') was unsuitable because the project specifications did not want the minute portion to be zero-padded. Here is a good post relating to this technique.
There is no single-digit minute option in TIME_FORMAT() or DATE_FORMAT().
If you are using MySQL 8.0+ you can use REGEXP_REPLACE like this to achieve a variable length string similar mickmackusa's answer:
REGEXP_REPLACE(SEC_TO_TIME(duration), '^(0|:)+', '')

Sum value by hourly for IST data in UTC database

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;

Finding available timeslots between dates

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

How do I convert negative time value into 24 hour time in MYSQL?

I have a column in a table of type TIME. I want to get a result that applies a time shift that results in a 24 hour clock representation of that shift. To add the shift, my query contains...
select addtime(boo,'01:00:00') as yada
But any value that gets taken out of the 24 hour range ends up outside the 24 hour range, such as...
23:45 ends up as 24:45 (when I want 00:45:00)
If I go the other way and subtract the hour from a value less than 1am, I get...
00:15 ends up as -00:45:00 when I want (23:15:00)
Now, I understand that the TIME format in MYSQL is "duration" and not the actual "time", but for the life of me I can't figure out how to convert to an actual clock time as outlined above. Please help me or kill me. Either will end my suffering.
A simple solution would be to just use a DATETIME data type instead, then ignore the date part. If you're not dealing with huge amounts of data, or searching by the actual times I can't see an issue.
As a bonus you'll be able to manipulate the data with the likes of + INTERVAL 1 HOUR etc.
When extracting it just use TIME(boo)
As you know, the MySQL TIME type is not restricted to 24 hour time so this is probably the closest you'll get... I'm sure you could construct a query using MOD() etc but it's probably not worth it.
A possible solution is just add your boo TIME value to any date (e.g. today) then add your time delta and after that just return time part with TIME()
SELECT TIME(CURDATE()
+ INTERVAL TIME_TO_SEC('23:45:00') SECOND
+ INTERVAL 1 HOUR) new_time
Output:
+----------+
| new_time |
+----------+
| 00:45:00 |
+----------+
Here is SQLFiddle demo