SQL Month selection with two parameters - mysql

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

Related

Access SQL - DateDiff Where it only looks for values that have existed over 2 weeks in the database

SELECT SerialNumber
FROM Warranty
WHERE (ABS(DateDiff('d', EndDate1, EndDate2)) > 7)
I currently have a query that shows me the Serial Numbers that have a difference of more than 7 days between the 2 dates. I want to add another condition where it will skip checking Serial Numbers that have been added to the database in the last 2 weeks
I'm just going to go ahead and add this as an answer, to make it clearer.
SELECT SerialNumber
FROM Warranty
WHERE (ABS(DateDiff('d', EndDate1, EndDate2)) > 7)
AND MyNewDateField >= DateAdd("d", -14, Date())
Essentially, this adds -14 days to the current date (or subtracts 2 weeks), and then only takes records where the DateAdded field (aka "MyNewDateField") is greater than, or equal to, that date. So, this will keep all records where DateAdded is within the most recent 2 weeks.

Return rows for next month, MYSQL

I have a mysql table which stores users' availability, stored in 'start' and 'end' columns as date fields.
I have a form where other users can search through the 'availabilty' with various periods like, today, tomorrow and next week . I'm trying to figure out how to construct the query to get all the rows for users who are available 'next month'.
The 'start' values maybe from today and the 'end' value might might be three months away but if next month falls between 'start' and 'end' then I would want that row returned.
The nearest I can get is with the query below but that just returns rows where 'start' falls within next month. Many thanks,
sql= "SELECT * FROM mytable WHERE start BETWEEN DATE_SUB(LAST_DAY(DATE_ADD(NOW(), INTERVAL 1 MONTH)),INTERVAL DAY(LAST_DAY(DATE_ADD(NOW(), INTERVAL 1 MONTH)))-1 DAY) AND LAST_DAY(DATE_ADD(NOW(), INTERVAL 1 MONTH))";
As you are interested in anything that happens in the full month following the current date you could try something like this:
SELECT * FROM mytable WHERE
FLOOR(start/100000000)<=FLOOR(NOW()/100000000)+1 AND
FLOOR( end/100000000)>=FLOOR(NOW()/100000000)+1
This query make use of the fact that datetime values are stored in MySql internally as a number like
SELECT now()+0
--> 20150906130640
where the digits 09 refer to the current month. FLOOR(NOW()/100000000) filters out the first digits of the number (in this case:201509). The WHERE conditions now simply test whether the start date is anywhere before the end of the next month and the end date is at least in or after the period of the next month.
(In my version I purposely left out the condition that start needs to be "after today", since a period that has started earlier seems in my eyes still applicable for your described purpose. If, however, you wanted that condition included too you could simply add an AND start > now() at the end of your WHERE clause.)
Edit
As your SQLfiddle is set-up with a date instead of a (as I was assuming) datetime column your dates will be represented differently in mumeric format like 20150907 and a simple division by 100 will now get you the desired month-number for comparison (201509):
SELECT * FROM mytable WHERE
FLOOR(start/100)<=FLOOR(NOW()/100000000)+1 AND
FLOOR( end/100)>=FLOOR(NOW()/100000000)+1
The number returned by NOW() is still a 14-digit figure and needs to be divided by 100000000. See your updated fiddle here: SQLfiddle
I also added another record ('Charlie') which does not fulfill your requirements.
Update
To better accommodate change-of-year scenarios I updated my SqlFiddle. The where clause is now based on 12*YEAR(..)+MONTH(..) type functions.

How to exclude weekends from DATE_SUB in 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.

MySQL range between dates: First order + 6 months

I'm using MySQL Workbench to run my query.
I want to run a couple of different date queries, I don't know if it's possible in SQL.
1) Run the report from the first date in the system to X date.
How can I find what the first orderID or date is as part of the calculations?
I know that if I have the date to begin with, I can use:
where T5.date_purchased BETWEEN '2005-01-01' AND '2015-12-31' OR:
where T5.date_purchased BETWEEN '2005-01-01' AND CURDATE() + INTERVAL 1 DAY
UPDATE
----- Query 2 has been answered (although open to any improvement) -----
2) Run the report from the first time a product shows up, to + 6 months (to see it's first 6 months of order) ie: Widget 1 (first order) + 6 months from order date. Something like:
where widget=widgetID AND date between widget1's first purchase and +6 months
Update: This doesn't work, however this is somewhat of what I was thinking:
where (T3.products_id = 39) and DATE_ADD((T1.products_date_added), INTERVAL 1 MONTH)
I would use my P3.products_date_added, however, I don't know how to use it as part of the above, correctly.
Are either of these possible, I know how to pull the records when I know the date, I just don't know if it can be done with 'date unknown' or if I have to run a "pre-report" first. Or is it a post processing filter in excel?
Thank you in advance.
Answering problem #2:
2) Run the report from the first time a product shows up, to + 6 months (to see it's first 6 months of order) ie: Widget 1 (first order) + 6 months from order date. Something like:
where widget=widgetID AND date between widget1's first purchase and +6 months
Answer:
-- Use for specific comparisons of products OR for the first X months of sales
where (T3.products_id = 39) and T5.date_purchased between T1.products_date_added and DATE_ADD((T1.products_date_added), INTERVAL 2 MONTH)
-- This results in PID: release: 10th July, +2 months; 10th Sep. 31 units.
OR
-- (T3.products_id = 11 or T3.products_id = 39) gives the results of the 2 product orders from release date to the first 2 months of each
-- (T3.products_id) gives all products, their first 2 months of release
-- (T3.products_id = 39) gives specific product release sales
-- Inspired by: http://stackoverflow.com/questions/28788691/mysql-range-between-dates-first-order-6-months?noredirect=1#comment45853546_28788691
If it is possible for your solution, try and run 2 separate queries:
- ONE for finding the date of first order
- then calculate +6 months from query 1 result
- AND the second one to get the purchases BETWEEN both dates

MySQL: Returning records from the current month and previous 3 months

I'm using PHP/MySQL booking system and i'm using a Google Line Chart to try and display the gross sales from the current month, and also the previous 3 months.
Each booking has a date in the standard phpmyadmin "date" format, so yyyy:mm:dd.
So, im looking to get 4 results from 4 queries, each query filtering out a certain month and grabbing the sum of each booking from that month.
My question is, how can i distinguish between the months in the query? How would i structure the query?
Based on the title:
select * from bookings where MONTH(CURDATE())=MONTH(booking_date);
select * from bookings where MONTH(booking_date) > MONTH(CURDATE()-INTERVAL 3 MONTH) and < MONTH(CURDATE() + INTERVAL 1 MONTH);
For simple per-month searches you can use the following:
Select * from bookings where MONTHNAME(booking_date)='July' and YEAR(booking_date)=2013;
Or:
Select * from bookings where MONTH(booking_date)=7 and YEAR(booking_date)=2013;
Also since you've already got the months, you could do this (this method requires that you maintain a table of ending dates for each month an compensate for leap year though):
select * from bookings where booking_date>'2013-06-30' AND booking_date<'2013-08-01';
In first place, excuse my english....
I know this is old thread and cant comment but, #AbsoluteƵERØ, that answer apply to the current month, in example, if i got records of July in 2013-2014-2015, the query will return the records on the month for those years.... To avoid that and using your posted code:
SELECT * FROM bookings WHERE MONTH(CURDATE()) = MONTH(booking_date) AND YEAR(CURDATE()) = YEAR(booking_date);
Note: if use the "name form" and specify the year there's no problem, like this:
SELECT * FROM bookings WHERE MONTH(CURDATE()) = MONTH(booking_date) AND YEAR(booking_date) = 2013;