Compare datetime using CASE - mysql

I have a database table of start time and end time of an event that takes place in the real world.
I believe the data type of the start time and end time is of the datetime/timestamp type inside the db. It is definitely not a string.
The records in the table look something like the below:
id | start time | end time
1 | 2020-08-18 10:00:00 | 2020-08-18 11:00:00
2 | 2020-08-18 19:00:00 | 2020-08-18 20:00:00
3 | 2020-08-18 05:00:00 | 2020-08-18 06:00:00
Right now, I am trying to do something like a classification to see if the event take place before / during/ after 'office/work hours'.
The column SamplingStart is the start time of the event.
The column SamplingEnd is the end time of the event.
Below is a portion of my query written in MySQL:
CASE
WHEN DATE_FORMAT(b01.SamplingStart, '%Y-%m-%d') = DATE_FORMAT(b01.SamplingEnd, '%Y-%m-%d') AND b01.Speed * 3.6 >= 5 THEN
CASE
WHEN TIME(b01.SamplingStart) >= '08:00:00' AND TIME(b01.SamplingEnd) <= '17:00:00' THEN "During office hours"
WHEN TIME(b01.SamplingStart) >= '17:01:00' AND TIME(b01.SamplingEnd) <= '23:59:00' THEN "After office hours"
WHEN TIME(b01.SamplingStart) >= '00:01:00' AND TIME(b01.SamplingEnd) <= '07:59:00' THEN "Before office hours"
END
WHEN b01.Speed = 0 THEN "No Usage"
END AS VUsage
My thought process was like this. I first determine if the start time and end time are of the same day and don't care about the time part of the datetime column. If they are of the same day. Then I just have to compare the hours to see if they are before/after office hours within the same day.
The way the code above written seemingly fulfills most of my records in the database table and I can get the string representation for most of my rows in the table.
But something wrong occurs for some specific time ranges. When the start time is for example 17 Aug 2020 11pm and the end time for that record is 18 Aug 2020 8:05am then the result of my query returns a blank for that particular row.
I guess this is because 17 Aug 11pm is the 'after hours', however the end time is 18 Aug 8:05am which is the 'before hours' range. I am guessing that because there is conflict, that is why the result for the particular row in the table is blank.
I was thinking the way to overcome this is to think that if the start time and end time are of a different day. i.e. 17 aug vs 18 aug. I can 'assume' that this is after hours. This feels slightly wrong. I am not 100% sure.
I also have a feeling that they may be other time frames which my CASE statement inside my SQL code cannot properly catch and resulting in a blank classification.
I feel that I may have missed out something and wanted to know if there a better/cleverer way for this situation?
Thank you!

I think you could safely say
WHEN TIME(b01.SamplingStart) >= '08:00:00' AND TIME(b01.SamplingEnd) <= '17:00:00' THEN "During office hours"
WHEN TIME(b01.SamplingStart) >= '17:00:01' THEN "After office hours"
WHEN TIME(b01.SamplingStart) >= '00:00:01' AND TIME(b01.SamplingEnd) <= '07:59:59' THEN "Before office hours"
If all you want to know is when the event started to signify After or Before office hours
Note I also made the time more precise so you dont miss any events

Related

Mysql: calculate length time between two times in AM and PM

I need to calculate the difference between two columns which are of type time. The fields are named start_time and end_time. I use the function timediff(s,e) and it works well but some times it doesn't. For example when end_time is 00:00 which is considered as 12 AM and start_time is 19:00 which is 7 PM the difference function shows 19 hours (actually I also select hour(timediff(s,e))) while I expect it to be 5 hours.
How can I fix this?
I tried this
case
when finish_time < start_time then TIMEDIFF(timestamp('2021:01:02',finish_time),timestamp('2021:01:01',start_time))
else TIMEDIFF(timestamp('2021:01:01',finish_time),timestamp('2021:01:01',start_time))
end as diff,
and it works
As 00:00:00 is considered the start of a new day or even if you have an end time that is the day after the start time you will have to make your start and end field into DATETIME types. Also if you want the difference between the 2 times you should be using timediff(end,start)

mysql select on datetime objects within range

I have a table 'appointments' that contains, among other things, two datetime fields labeled 'start' and 'end'. I also have date in local time that is converted as a range of a full day into UTC (which is what the SQL table stores the datetimes as). I need to select all the (business) times between 00:00:00 and 08:00:00 UTC that also fall in the range of my local time conversion.
An example, A user in PST (pacific standard time) picks December 1st, 2018. The dates between December 1st at 00:00:00 and December 2nd 00:00:00 are converted to UTC which would be December 1st 08:00:00 to December 2nd 08:00:00. I need to select all appointments between 00:00:00 and 8:00:00 any given day in the previous range (dec 1 - dec 2).
All of my datetimes/queries are in the form 'yyyy-MM-dd HH:mm:ss'.
I know that I can select all of the times between two times rather simply like so:
SELECT start, end
FROM appointment
WHERE start>='2018-12-01 00:00:00'
AND end<='2018-12-02 08:00:00'
But I'm unsure as to how to trim these down to only between business hours.
I'm looking for something like
SELECT start, end
FROM appointment
WHERE (start>='2018-12-01 00:00:00'
AND end<='2018-12-02 08:00:00')
AND (start.substring(11, start.end) >= '00:00:00'
AND end.substring(11, end.end) <= '08:00:00')
Where a call like start.substring(11, start.end) would return the time in 'HH:mm:ss' format
Try using the TIME function in MySQL.
SELECT start, end
FROM appointment
WHERE TIME(start) >= '00:00:00'
AND TIME(end) <= '08:00:00' AND ... //other conditions

How to design table structure for Operating Hours

Problem #1:
How can the table be designed in MySQL in efficient way to structure
1) Store Opening Time,
2) Break Time and
3) Closing Time in a day
For an instance, On Sunday: Opening Time: 7:00AM, Closing Time: 5:00PM, Break Time Start: 1:00PM, Break Time End: 2:30PM.
Problem #2:
How to define the query to search that table for all Stores that are being Opened/Closed between the given range.
For an instance, If user tries to filter the stores for Opening between 9:00AM and 12:00AM. How can I apply query for this filter since it might be possible the Break Time or Closing Time could be within that timeframe.
store_id day open_time break_start break_end close_time
1 mon 7:00AM 1:00PM 2:30PM 5:00PM
1 tue 7:00AM 1:00PM 2:30PM 5:00PM
1 wed 7:00AM 1:00PM 2:30PM 5:00PM
1 thu 7:00AM 1:00PM 2:30PM 5:00PM
1 fri 7:00AM 1:00PM 2:30PM 5:00PM
1 sat Closed
1 sun Closed
Something similar to this. If the user uses criteria: Open Time between: 8:00AM to 2:00PM; to search the store then He must be able to see all the stores that are opened during that timeframe. This timeframe must also include with store open_time. That is, based on criteria provided, the store is Open at 7:00AM, 8:00AM and 9:00AM and until 2:PM.
Better to create three different columns, since you want to query between
Opening time , closing time or break time
create table store_timing
(
store_id int, -- from store table
Opening_Time datetime,
break_time datetime,
closing_time datetime
)
Query :
select *
from store_timing
where Opening_Time<= 'Opening_Time'
and closing_time <= 'closing_time'

Mysql delete from table where date is 'yesterday' but ignoring the time stamp

I have a table in Mysql which has column called 'dep_timestamp' which holds data in the following format (the data is received from a external source so can't be changed, and is displayed via web queries so can't be modified within that table)
2015-05-12 19:18:00 +0100
The database holds cancellations for booked taxi journeys which get pushed out to me from a central booking system in realtime. Throughout the day I will get any number of messages for cancelled journeys. A journey has a booked departure time dep_timestamp in its full format of 2015-05-12 19:18:00 +0100 that is used for reporting and all sort of other things.
Every day at 03:00 I want to delete all of the cancelled journeys that where due to depart 'yesterday' This means when my users do a query and ask what journeys have been cancelled today they only see stuff that has a booked departure of today.
I have an event setup on the server to delete rows older then 1 day using the following code;
DELETE FROM db.canx_today WHERE 'dep_timestamp' < DATE_SUB(CURRENT_TIME() , INTERVAL 1 DAY)
That event is set to run every day at 03:00 and does without error. However it takes the full date/time into consideration when running which means it only deletes the rows where the time & date are both older than one day.
If I swap CURRENT_TIME with CURRENT_DATE then the server throws this error; Truncated incorrect datetime value: '2015-05-13 10:17:00 +0100' which makes sense in so far that its looking for a full date/time string.
Is there a way to ignore the time element and just delete all rows that are from the previous day?
You can calculate based on CURRENT_DATE() and just concatenate 00:00:00 to that value.
WHERE `dep_timestamp` < CONCAT(CURRENT_DATE(), ' 00:00:00')
This should work, but will only be noticeably faster than the one I originally put in the comments above if dep_timestamp is indexed.
WHERE `dep_timestamp` < DATE_FORMAT(curdate(), "%Y-%m-%d 00:00:00")
Since DATE_FORMAT() actually returns a string, this might be more efficient when indexes are actually needed:
WHERE `dep_timestamp` < CAST(DATE_FORMAT(curdate(), "%Y-%m-%d 00:00:00") AS DATETIME)
DELETE FROM `canx_today`
WHERE DATE(`dep_timestamp`) = DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY);

MySQL custom datetime

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).