MySQL add date fields and compare to today on where clause - mysql

I am struggling with this one and getting a syntax error.
Trying to get campaigns that are still ongoing, ie, where start_date + duration_days is >= than today.
I've also tried with DATE_ADD with the same result.
start_date is a DATE field, while duration_days is INT.
SELECT id,start_date,duration_days
FROM `myTable`
WHERE start_date + INTERVAL duration_days DAYS >= CURDATE()
Thanks

Change the interval to DAY not DAYS, that's what is throwing the error.
SELECT id,start_date,duration_days
FROM `myTable`
WHERE start_date + INTERVAL duration_days DAY >= CURDATE()

You need to use the DATE_ADD and DATE_SUB functions to manipulate dates rather than the arithmetic operators:
SELECT id,start_date,duration_days
FROM `myTable`
WHERE DATE_ADD(start_date, INTERVAL duration_days DAYS) >= CURDATE()

Related

MySQL 5.6 - select results where the most recent of multiple datetime columns is 1 month ago at least

I have a table with multiple datetime columns in a mySQL 5.6 database.
email_id
email_sent_date (datetime)
email_replied_date (datetime)
email_bounced_date(datetime)
email_archived (datetime)
I want to retrieve all emails where the latest datetime of the group (email_sent_date,email_replied_date, email_bounced_date, email_archived) is at least 1 month ago from today.
I would like to do something like this, even though i think I can't use this max(), but you'll get a sense of what I am trying to achieve:
SELECT *
FROM table
WHERE MAX(email_sent_date,email_replied_date, email_bounced_date, email_archived) <= CURDATE() - INTERVAL 30 DAY
How to achieve this ?
You want the function greatest(), not max():
SELECT *
FROM table
WHERE GREATEST(email_sent_date, email_replied_date, email_bounced_date, email_archive) <= CURDATE() - INTERVAL 30 DAY;
Note: If any of the values are NULL, then the row will be filtered out.
I prefer explicit comparisons because I think the logic is easier to follow:
SELECT *
FROM table
WHERE email_sent_date <= CURDATE() - INTERVAL 30 DAY AND
email_replied_date <= CURDATE() - INTERVAL 30 DAY AND
email_bounced_date <= CURDATE() - INTERVAL 30 DAY AND
email_archive <= CURDATE() - INTERVAL 30 DAY;
EDIT:
Handling NULL values requires explicit checks. Perhaps:
SELECT *
FROM table
WHERE (email_sent_date <= CURDATE() - INTERVAL 30 DAY OR email_sent_date IS NULL) AND
(email_replied_date <= CURDATE() - INTERVAL 30 DAY OR email_replied_date IS NULL) AND
(email_bounced_date <= CURDATE() - INTERVAL 30 DAY OR email_bounced_date IS NULL) AND
(email_archive <= CURDATE() - INTERVAL 30 DAY OR email_archive IS NULL);

comparing dates by month and year in mysql

I have a table containing data about events and festivals with following columns recording their start and end dates.
Start_Date
End_Date
date format is in YYYY-MM-DD. I need to fetch event details with the following condition.
Need to fetch all events which start with a current month and there end dates can be anything say currentDate+next30days.
I am clear about end date concept. but not sure how I can fetch data whose start dates are in a current month.
For this, I need to compare current year and current month against the Start_Date column in my database.
Can anyone help me to point out as how I can do that?
select * from your_table
where year(Start_Date) = year(curdate())
and month(Start_Date) = month(curdate())
and end_date <= curdate() + interval 30 day
I don't like either of the other two answers, because they do not let the optimizer use an index on start_date. For that, the functions need to be on the current date side.
So, I would go for:
where start_date >= date_add(curdate(), interval 1 - day(curdate()) day) and
start_date < date_add(date_add(curdate(), interval 1 - day(curdate()) day), interval 1 month)
All the date functions are on curdate(), which does not affect the ability of MySQL to use an index in this case.
You can also include the condition on end_date:
where (start_date >= date_add(curdate(), interval 1 - day(curdate()) day) and
start_date < date_add(date_add(curdate(), interval 1 - day(curdate()) day), interval 1 month)
) and
end_date <= date_add(curdate(), interval 30 day)
This can still take advantage of an index.
DateTime functions are your friends:
SELECT
*
FROM
`event`
WHERE
(MONTH(NOW()) = MONTH(`Start_Date`))
AND
(`End_Date` <= (NOW() + INTERVAL 30 DAY))
AND
(YEAR(NOW()) = YEAR(`Start_Date`))
Comparing the year and month separately feels messy. I like to contain it in one line. I doubt it will make a noticeable difference in performance, so its purely personal preference.
select * from your_table
where LAST_DAY(Start_Date) = LAST_DAY(curdate())
and end_date <= curdate() + interval 30 day
So all I'm doing is using the last_day function to check the last day of the month of each date and then comparing this common denominator. You could also use
where DATE_FORMAT(Start_Date ,'%Y-%m-01') = DATE_FORMAT(curdate(),'%Y-%m-01')

how to filter a select statement in mysql for a particular time period without using now()

I have tried to filter records but with the use of now function as given below
select * from table where date>= DATE_SUB( NOW( ) ,INTERVAL 90 DAY )
What I need is a select statement that can filter its records for a week or month from the current date but without using NOW() function
if you are using java you could make use of the following code
String timeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Calendar.getInstance().getTime());
or you could use curdate() of mysql
Since I found it hard to understand the question I provide the following possibilities:
Try for all dates in a week from now:
SELECT * FROM table
WHERE date BETWEEN CURDATE() AND DATE_ADD(CURDATE() ,INTERVAL 1 WEEK)
and for all dates in a month from now:
SELECT * FROM table
WHERE date BETWEEN CURDATE() AND DATE_ADD(CURDATE() ,INTERVAL 1 MONTH)
If you are looking for all dates of the current month use
SELECT * FROM table
WHERE MONTH(date)=MONTH(CURDATE()) AND YEAR(date)=YEAR(CURDATE())
or for all dates of the current week use
SELECT * FROM table
WHERE WEEK(date)=WEEK(CURDATE()) AND YEAR(date)=YEAR(CURDATE())

How to write this mysql where clause?

I have a field date_purchased and date_ordered which are datetime fields. Now I need to fetch the record if the product was purchased after order, and if the puchase was 2 days earlier or 7 days after order:
if(date_purchased>date_ordered)
{
if(date_purchased>(today-2) or date_puchased<(date_ordered+7))
}
Basically, how do I translate the above code to mysql where condition( nested and/or)?
Use DATE_SUB() and DATE_ADD() to add days to a datetime field. The two date comparisons are enclosed in () as a single component to the AND.
WHERE
date_purchased > date_ordered
AND (
date_purchased > DATE_SUB(NOW(), INTERVAL 2 DAY)
OR date_purchased < DATE_ADD(date_ordered, INTERVAL 7 DAY)
)
Note If these are DATETIME fields rather than DATE fields, you may want to strip off the time portion with DATE() so that the day comparisons start at the beginning of the day, rather than some 24 hour interval from the current time. This also means using CURDATE() instead of NOW() to get today's date rather than a timestamp.
WHERE
date_purchased > date_ordered
AND (
DATE(date_purchased) > DATE_SUB(CURDATE(), INTERVAL 2 DAY)
OR DATE(date_purchased) < DATE_ADD(DATE(date_ordered), INTERVAL 7 DAY)
)
Use the BETWEEN operator to select the interval.
WHERE d BETWEEN *date-2 AND *date+7
SELECT * FROM your_table
WHERE date_purchased > date_ordered
AND (DATE_DIFF(date_purchased, date_ordered) > 2
OR DATE_DIFF(date_purchased, date_ordered) < -7)

How to do : "Between TODAY AND TODAY-7"?

I need to find the account created for the current day, et for the last 7 days.
To find my results for today, it works, and I do this :
SELECT * FROM `account` where DATE(created_at) = DATE(NOW())
But I don't know how to do to get the last 7days account.
I tried something like this, but without success :
SELECT * FROM `account` where DATE(created_at) BETWEEN DATE(NOW()) AND DATE(NOW()-7)
Have you an idea ?
in mysql:
SELECT * FROM `account`
WHERE DATE(created_at) > (NOW() - INTERVAL 7 DAY)
Try:
BETWEEN (NOW() - INTERVAL 7 DAY) AND NOW()
If created_at has an index and you wouldn't like to prevent the optimiser from using it, I would recommend the following pattern (assuming created_at contains both date and time):
WHERE created_at >= CURRENT_DATE - INTERVAL 7 DAY
AND created_at < CURRENT_DATE + INTERVAL 1 DAY
This spans the range from the day exactly one week ago till today (inclusive), so 8 days in total.
also have a look at MySQL functions ADDDATE(), DATE_ADD(), DATE_SUB()
e.g.
ADDDATE(DATE(NOW()), -7)