How to exclude weekends from DATE_SUB in mysql - mysql

Does anyone know how to exclude weekends from the DATE_SUB function in MYSQL? I am looking to search the past 1500 working days from CURDATE() but am struggling with the solution?
Much appreciate any guidance.
I recognise this question was asked on stackoverflow before (see link below) but I could not get his solution to work
How do you exclude weekends from a date_sub?

SET #zi = '2015.07.25';
SET #n =6;
SELECT DATE_SUB(
#zi,
INTERVAL CASE
WHEN DAYOFWEEK(#zi)=1 THEN (#n +(FLOOR((#n-0.5)/5)+1)*2 - 1)
WHEN DAYOFWEEK(#zi)=2 THEN (#n +(FLOOR((#n-0.5)/5)+1)*2)
WHEN DAYOFWEEK(#zi)=3 THEN (#n-1 +(FLOOR(((#n-1)-0.5)/5)+1)*2 + 1)
WHEN DAYOFWEEK(#zi)=4 THEN (#n-2 +(FLOOR(((#n-2)-0.5)/5)+1)*2 + 2)
WHEN DAYOFWEEK(#zi)=5 THEN (#n-3 +(FLOOR(((#n-3)-0.5)/5)+1)*2 + 3)
WHEN DAYOFWEEK(#zi)=6 THEN (#n-4 +(FLOOR(((#n-4)-0.5)/5)+1)*2 + 4)
WHEN DAYOFWEEK(#zi)=7 THEN (#n-5 +(FLOOR(((#n-5)-0.5)/5)+1)*2 + 5)
END DAY
);
#zi is the date. You can give any date.
#n is the number of WORKING days you want subtracted.
The answer given didn't work for me, it sometimes even gave dates in the future, it returned dates that were sundays or other errors like that.

Related

I want to find the previous month's date for specific date in SQL

I want to get the previous month date for specific dates in SQL. For example: 6.21.19 has a previous month date of 5.21.19.
I am just trying to get comps from this.
MONTH( curdate() ) -1
I need to return the previous month date.
Welcome to the board Arie. Judging from your question and responses, you need a range of dates and their prior month relations. The easiest way would be for all of the dates you need to look up to be in a table, then the answers provided so far would work. Since that doesn't appear to be the case, I'm guessing you are creating date ranges on the fly.
So lets assume you need exactly the data shown in your example, there are two parts to this, first you need to get a list of days that you want to look up, then you need to get the day in the prior month. There are lots of ways to get a sequence of days, but for simplicity I'll use a recursive CTE. Once I have the date range, I'll just select the dates and their prior month date as well.
with Date_CTE as (select cast('6/1/2019' as datetime) as repDate
union all
select dateadd(day, 1, repdate) as repDate
from Date_CTE
where repDate < '06/07/2019')
select repDate, dateadd(month, -1, repDate) as PriorDate
from Date_CTE
CTEs are helpful functions and you can get more details on them here, but it's worth noting there are many ways to do this. Hope this gets you pointed in the right direction.
SELECT yourDateColumn, yourDateColumn-interval 1 month as prevMonthDate

Can mySQL find different things in the same query

In this query which I got help from #jarlh, in this question ORDER BY CASE
SELECT *
FROM booking
WHERE booking_date=$b_date OR DATE(delivery_date)=$b_date
ORDER BY CASE WHEN booking_date=$b_date
THEN hour * 60 + minute
WHEN DATE(delivery_date)=$b_date
THEN HOUR(delivery_date) * 60 + MINUTE(delivery_date)
END ASC
I need to find those posts with the same HOUR and MINUTE, before I leave the query, and mark them somehow, so I’m able to print them (those in the same hour and minute) horizontally and not vertically.

SQL using sysdate

I have updated the value of the SAD_PB_CAS_STATDT field equal to sysdate which is the date today. The problem now is when i query something with that SAD_PB_CAS_STATDT = sysdate, it does not return anything.
see my sql code below:
SELECT EMPLID, ACAD_CAREER, STDNT_CAR_NBR, ADM_APPL_NBR, APPL_PROG_NBR,
SAD_PB_CAS_STATUS, SAD_PB_CAS_STATDT
FROM PS_SAD_PB_CAS
WHERE SAD_PB_CAS_STATUS IN ('ASG', 'USD')
AND SAD_PB_CAS_STATDT = sysdate;
I'm guessing it has something to do with the return type of sysdate? does it return something with date and time? any help would be appreciated for me to be able to pull the query with sysdate in the conditions.
As others have mentioned, always check the documentation (including Stack Overflow) before you post a question. There are several ways to make your query work, but I would recommend the following WHERE clause:
WHERE
SAD_PB_CAS_STATUS IN ('ASG', 'USD') AND
SAD_PB_CAS_STATDT >= CURDATE() AND -- today at midnight
SAD_PB_CAS_STATDT < CURDATE() + INTERVAL 1 DAY; -- tomorrow at midnight
The reason why this approach is favored over casting your SAD_PB_CAS_STADT column to a date only, is that the above allows an index to be used on the column, if it exists.

Mysql: Round datetime to seconds - some issues 24h

i spend time to solve my issue on my own and also read through many posts in here but somehow i cannot find a working solution for me.
I'm collecting different values from my smarthome in an mysqldb. To run some analysis on the data i need to round a datetime value in one usecase. I must get rid of the seconds.
What I tried/found where different approaches (even via Unixtime) but nothing solved my issue. Within this forum i found an old thread with the following hint:
extract from my insert script:
CONVERT(
CONCAT(
date(`detailed-data-integration`.`timestamp`),
' ',
SEC_TO_TIME((ROUND(TIME_TO_SEC(`detailed-data-integration`.`timestamp`)/60)) * 60)
) , Datetime) AS `timestamp-rnd`
This looks fine and works on the first view, but:
Timestamp: 2018-02-03 23:59:56 leads to a NULL because of an invalid datetime value. The function wants to create: 2018-02-03 24:00:00 which is wrong.
Can somebody of you give me a hint how to handle / solve this issue?
Thx and KR
i identified a solution which will work for my requirements which i want to share with you:
CASE
when second(`detailed-data`.`timestamp`) >= 30 then DATE_FORMAT(`detailed-data`.`timestamp`, '%Y-%m-%d %H:%i:00') + interval 1 minute
when second(`detailed-data`.`timestamp`) < 30 then DATE_FORMAT(`detailed-data`.`timestamp`, '%Y-%m-%d %H:%i:00')
END as testcase
Why are you using time_to_sec()? You should be using to_seconds()
'0000-01-01' + interval round(to_seconds(`detailed-data-integration`.`timestamp`)/60)) * 60) second - interval 1 day as `timestamp-rnd`
In other words, don't separate the date from the time. Just handle the entire date/time as a single value.

SQL Month selection with two parameters

In a table I have a column called 'service_time' which is the start date of a service, and another column 'times_year' which is how many times per year the service shall be done.
The problem I have is how I should select the rows when -> (thisMonth == service_time (month)) OR (thisMonth == service_time (month) + 12/times_year)
The tricky part that I cannot solve is how should I do this if the 'times_year' is a value between 1-4? Without making 4 different OR's??
So should it be something of a loop decided by the 'times_year' instead of doing a OR query to check all 4 OR's every single time even if the 'times_year' isn't 4?
UPDATE:
Well I need help how to do a loop in the sql query statement wich will only select if the 'month' is correct, so basiclly now its the '08' and if the service_time is set to 2015-03-01 (day doesnt matter) it shall do a check with the times_year to check if 2015-03-01 shall be having a service > 2015-03 + 12/4(as an example) then 2015-06, 2015-09, 2015-12, 2016-03 Then no dont select and so on...
I could do this in PHP but it will not be efficent in the longer term
Hopefully, you don't have times_year values like 5, 11, and so forth. That will get a little nasty to work out. Values like 1,2,3,4,6,12 are good.
You can determine the next service time after the start time like this in MySQL
service_time + INTERVAL (12 DIV times_year) MONTH
Similarly, the third service time after the start time will work like this.
service_time + INTERVAL 3*(12 DIV times_year) MONTH
Maybe your business rules call for service to be due on or before the last calendar day of each month. You can display that like so.
LAST_DAY(service_time + INTERVAL 3*(12 DIV times_year) MONTH)
Finally, you may wish to display the next service due date after today (after CURDATE()) How do you do that?
First, it has been this many months since the first service time:
TIMESTAMPDIFF(MONTH, service_time, CURDATE())
Next, you want to know how many service intervals that covers. Easy:
times_year * TIMESTAMPDIFF(MONTH, service_time, CURDATE()) / 12.0
Next, you want the next highest service interval number:
CEIL(times_year * TIMESTAMPDIFF(MONTH, CURDATE(), service_time) / 12.0)
Finally, plug that into the next-service-time function:
service_time + INTERVAL
CEIL(times_year * TIMESTAMPDIFF(MONTH, service_time, CURDATE()) / 12.0)*
(12 DIV times_year) MONTH
It's a long formula, but it works.
Finally, you can use this WHERE clause to find out all the services due before the end of the present month.
WHERE LAST_DAY(service_time + INTERVAL
CEIL(times_year * TIMESTAMPDIFF(MONTH, service_time, CURDATE()) / 12.0)*
(12 DIV times_year) MONTH) <= LAST_DAY(CURDATE())