MYSQL Queries to find immediate next DateTime - mysql

I was writing a mini scheduler that perform certain task.
For calculating trigger time, I am using MYSQL. I am stucked at writing one of the query.
Find immediate DateTime which is greater than the given prevtime,
AND
the Day of the required immediate datetime should be ANY of given days
AND
time(HH:MM:SS) portion of required immediate datetime should be equal to given time.
Examples:
(a)
If given days are ('MON', 'WEDNES', 'SAT'),
given time is 10:15:00,
given prevtime is 2014-11-12 23:17:00
Then MYSQL should return
2014-11-15 10:15:00
(b)
Given Days: ('SUN','SAT','TUES')
Given Time: 09:10:00
Given prevtime is 2014-11-30 07:05:12
MYSQL should return 2014-11-30 09:10:00
(c)
Given Days: ('MON','THURS','SAT')
Given Time: 11:00:00
Given prevtime is 2014-12-29 11:55:12
MYSQL should return 2015-01-01 11:00:00
(d)
Days: (SUN, THURS, SAT)'
Given prevtime is 2014-02-27 18:15:00
Given Time 15:15:00
MYSQL Query result: 2014-03-01 15:15:00
(e)
DAYS: (TUES, WED, FRI)
Prev Date: 2014-12-23 09:30:00
Time : 08:00:00
Expected Result:
2014-12-24 08:00:00
(f)
DAYS: SUN, TUES, THURS
Prev Date: 2014-07-31 10:10:00
Time: 06:07:08
Expected Res:
2014-08-03 06:07:08

Using numeric weekday numbers, 0=Monday, 6=Sunday:
set #day1=0;
set #day2=2;
set #day3=5;
set #time=time('10:15:00');
set #prevtime=timestamp('2014-11-12 23:17:00');
select if(weekday(#nexttime:=date_add(concat(date(#prevtime),' ',#time),interval if(#time>time(#prevtime),0,1) day)) in (#day1,#day2,#day3),#nexttime,if(weekday(#nexttime:=date_add(#nexttime,interval 1 day)) in (#day1,#day2,#day3),#nexttime,if(weekday(#nexttime:=date_add(#nexttime,interval 1 day)) in (#day1,#day2,#day3),#nexttime,if(weekday(#nexttime:=date_add(#nexttime,interval 1 day)) in (#day1,#day2,#day3),#nexttime,if(weekday(#nexttime:=date_add(#nexttime,interval 1 day)) in (#day1,#day2,#day3),#nexttime,if(weekday(#nexttime:=date_add(#nexttime,interval 1 day)) in (#day1,#day2,#day3),#nexttime,date_add(#nexttime,interval 1 day))))))) as nexttime;
If you have only one weekday, you can set all three variables to the same number.

You should be able to formulate the where clause using the DAYNAME(), HOUR(), MINUTE() and SECOND() functions:
https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
If performance is inadequate and you start wishing you could index on DAYNAME(columname) for example, you can consider denormalizing your data and storing the DAYNAME value separately.
It might be simpler to switch to Postgres at that point though:
http://www.postgresql.org/docs/9.1/static/indexes-expressional.html

Related

Add weekend values to Monday SQL

I am working in mySQL and I currently have a count of total orders by day, but I would like to add Saturday and Sunday orders to Monday then remove Saturday and Sunday values. I have done some research on this but I cannot seem to find anything similar to what I am trying to do.
My current data table looks like this:
Date | Daily Count
8-6-2020 25
8-7-2020 82
8-8-2020 24
8-9-2020 33
8-10-2020 18
8-11-2020 10
8-12-2020 25
8-13-2020 15
I need it to look something like this:
Date | Daily Count
8-6-2020 25
8-7-2020 82
8-10-2020 75
8-11-2020 10
8-12-2020 25
8-13-2020 15
In this one the Daily counts for the 8th and 9th are added to the 10th, then removed, because they are weekend days. Thank you in advance for your help!
Consider using a case expression to adjust the date:
select
case weekday(date)
when 5 then date + interval 2 day
when 6 then date + interval 1 day
else date
end as new_date,
sum(daily_count) as daily_count
from mytable
group by new_date

MySQL, grouping by and performing a SUM within the groups

The table below contains records of shifts which have taken place. The start and end fields are the start and end timestamps of those shifts. I'm looking to build a query that will extract the total hours per month that the shifts cover.
Example table:
ID Start End
1 2018-10-23 10:30:00 2018-10-23 11:45:00
2 2018-10-22 22:00:00 2018-10-22 23:00:00
3 2018-11-22 22:00:00 2018-11-22 23:00:00
The ideal output would read:
Month Hours
10 2:15
11 1:00
I've got some of the elements worked out, using a SUM(timediff(end,start)) and GROUP BY, but havn't managed to get something good out!
Thanks!
Here you go:
select
month(start) as month,
time_format(sec_to_time(
sum(timestampdiff(second, start, end))
), '%H:%i') as hours,
sum(timestampdiff(second, start, end)) as seconds
from shift
group by month(start)
Result:
month hours seconds
----- ----- -------
10 02:15 8,100
11 01:00 3,600
Note: I added the extra column seconds in case you want to use this numeric value to do some extra processing.

How to get all rows where date is in a specific range at a given period?

How can I select all rows from a table where a date column is within a specific range of dates, at a given period (e.g. every 14 days)?
The table has a date column with most every date represented, possibly multiple times. The range is defined by a start date and an end date. The period is a number of days. For example:
Start: 2016-01-01 (friday)
End: 2016-12-31 (saturday)
period: 14 (days)
For the above, the query should return rows for every other Friday in 2016. That is, it should return the rows for the following dates:
2016-01-01
2016-01-15
2016-01-29
2016-02-12
2016-02-26
2016-03-11
2016-03-25
2016-04-08
2016-04-22
2016-05-06
2016-05-20
2016-06-03
2016-06-17
2016-07-01
2016-07-15
2016-07-29
2016-08-12
2016-08-26
2016-09-09
2016-09-23
2016-10-07
2016-10-21
2016-11-04
2016-11-18
2016-12-02
2016-12-16
2016-12-30
Currently, this is done in a stored procedure where a loop fills a temp table with the target dates, which is later joined on. However, I am trying to rewrite this code to step away from stored procedures.
What would be the best way to get the desired rows without using the stored procedure & a temp table? Keep in mind that (one of) the table(s) is quite large at around 1M records indexed on date, so any calculated values might impact the performance severely.
Alternatively, I could calculate all dates in the interval in PHP/RoR and use a massive IN clause, but hopefully there is a better solution.
Try this:
table_name1 is your table
date1 the date field
"2022-01-02" the start (twice included)
"2022-01-10" the end
3 the interval
SELECT date1
FROM table_name1
WHERE date1 BETWEEN "2022-01-02" AND "2022-01-10"
AND (DATE("2022-01-02") - date1) % 3 = 0;
Tested it with MySQL 5.6.

MySQL date_add behaviour

I've written some SQL to give me a range of dates between two times like so:
select date_add(x.min_date, interval ((t500.id-1) * 30) minute) period
from (
select '2013-08-05T23:00' as min_date, '2013-08-06T01:00' as max_date
) x,
t500
where date_add(x.min_date, interval ((t500.id-1) * 30) minute) <= x.max_date);
Where T500 is a trivial table with column id of 1 to 500 I use for simulating a loop.
Now I expect this to return:
2013-08-05 23:00:00
2013-08-05 23:30:00
2013-08-06 00:00:00
2013-08-06 00:30:00
2013-08-06 01:00:00
and finish there. But instead it carries on until 2013-08-06 23:30:00. I tried different max dates and it always returns dates to the end of the day. Could someone explain what's happening and how to make it stop when I want?
First thing that comes to mind would be casting your date strings into a date format instead of a string for example:
cast('2013-08-05T23:00' as smalldatetime)

Summing value differences across date range

My table is defined as follows:
DATETIME ENERGY VALUE
01/01/2013 00:00:00 1000
...
01/01/2013 08:00:00 2000
...
06/30/2013 00:00:00 10000
...
06/30/2013 08:00:00 12000
I need to calculate total energy value between: start hour of 00:00:00 and end hour 08:00:00 in a single day then sum these values for date range between 01/01/2013 and 06/30/2013.
Any idea will be appreciated.
Pseudo code:
SELECT SUM(DAILYENERGYSUM)
FROM
(SELECT SUM(ENGERGY) as DAILYENERGYSUM
FROM TABLE
WHERE DATEPART(DATETIME) >= '1/1/2013' and DATEPART(DATETIME) <= '6/30/2013' and TIMEPART(DATETIME) >= 0 and TIMEPART(DATETIME) <= 8
GROUP BY DATEPART(DATETIME)) AS DAYSUMS