Select next 7 days using only day and month - mysql

I have a table with birthdays in them, formatted in YYYY-MM-DD. My aim is to return results if the birthday is within the next 7 days.
I need it to use only the month and day, because if it reads the year also, a birthday in 1993 is never going to be within the next 7 days. It also needs take month changes into consideration.
For example, if its the 28th of Feb, and a birthday in the table is on the 1st March, that would be within 7 days, but not within the same month.
SELECT * FROM user WHERE DATE_FORMAT(birthday, '%m-%d') >= DATE_FORMAT(NOW() - INTERVAL 7 DAY, '%m-%d')
This is where i'm at, at the moment, but I know i'm miles off.

You need to format both of your dates in the WHERE clause.
SELECT *
FROM user
WHERE DATE_FORMAT(birthday, '%m-%d') BETWEEN DATE_FORMAT(NOW(), '%m-%d') AND DATE_FORMAT(DATE_ADD(NOW(), INTERVAL 7 DAY), '%m-%d')

retrieve current year with YEAR(CURDATE(), make a date biy concatenating with month and day coming from birthday and remove 7 days, check if curdate is in the range :
select *
from user
where
Curdate() between date_sub(CONCAT(YEAR(CURDATE()),'-', date_format(birthday, '%m-%d')), interval 7 day)
and CONCAT(YEAR(CURDATE()),'-', date_format(birthday, '%m-%d')) ;

Take year part from today's date and concatenate it with the month and day part of the dob column value. And cast that string to date. Then use that as a sub-query and check whether thet new column day difference is between 0 and 7.
Query
SELECT t.* -- select except the `new_col`
FROM (SELECT *,
CAST((Concat(YEAR(NOW()), '-', DATE_FORMAT(dob, '%m-%d'))) AS DATE
) AS
`new_col`
FROM `user`)t
WHERE DATEDIFF(t.`new_col`, NOW()) BETWEEN 0 AND 7;

Related

Get 5 next birthdays including next year

I have this query that takes the next 5 people who have a birthday.
SELECT *
FROM `user`
WHERE DATE_FORMAT(birth_date, '%m-%d') > date_format(curdate(), '%m-%d')
ORDER BY DATE_FORMAT(birth_date, '%m-%d')
LIMIT 5
Working great but when it's for example 12 december it does not take the people from the next year 12 january.
How could I do this?
Your query doesn't work because:
1. You only compare Month and Day and don't compare Year. You also should compare Year
2. You should calculate the next date of birthday.
For example:
SELECT *
FROM `user`
WHERE (birth_date + INTERVAL (YEAR(NOW())-YEAR(birth_date) + IF(DAYOFYEAR(NOW()) >= DAYOFYEAR(birth_date), 1, 0)) YEAR) > CURDATE()
ORDER BY DATE_FORMAT(birth_date, '%m-%d')
LIMIT 5
Basically, you just need to take the months, and add 12 to any months that are greater or equal to the current month, and this should give you a recursive month order:
select name,
month(STR_TO_DATE(birth_date, "%m-%d")) AS birth_month,
if(
month(STR_TO_DATE(birth_date, "%m-%d")) >= month(now()),
month(STR_TO_DATE(birth_date, "%m-%d")),
month(STR_TO_DATE(birth_date, "%m-%d")) + 12
) month_order
from `user`
order by month_order
limit 5
The STR_TO_DATE isn't needed if you're using DATETIME
Note: This won't work for multiple years in a row. Just into the next year.

Selecting all rows from last month onward

I'm trying to select all the data from the previous month to all the months in the future .. for example , I'd like to select everything from January till any date available in the future on the database, that goes for any month .. select the previous month till the future months of this year
This is my QUERY, It only starts with February , how can I make it start with the previous month .. current month - 1 is not working
SELECT *
FROM events
WHERE YEAR(event_start_date) = YEAR(CURDATE())
AND MONTH(event_start_date) = MONTH(CURDATE())
use DATE_SUB() to select previous month and >= to select all data in the future:
SELECT *
FROM events
WHERE YEAR(event_start_date) = YEAR(CURDATE())
AND MONTH(event_start_date) >= MONTH(DATE_SUB( CURDATE(), INTERVAL 1 MONTH))
Try:
AND MONTH(event_start_date) = MONTH(DATE_SUB(CURDATE(), INTERVAL 1 MONTHS))
The portion DATE_SUB(CURDATE(), INTERVAL 1 MONTH) will subtract a month from the current date. If you want last month and everything in the future, use:
AND MONTH(event_start_date) >= MONTH(DATE_SUB(CURDATE(), INTERVAL 1 MONTHS))
Notice '>='. Although there is an edge case at january that you'll have to get around. The best way might be like this:
WHERE event_start_date >= DATE_SUB(DATE_SUB(CURDATE(), INTERVAL 1 MONTHS), (DAYOFMONTH(CURDATE)) DAYS)
Which will get you everything from the 1st of last month. No edge cases.
Try this
SELECT *
FROM events
WHERE YEAR(event_start_date) = YEAR(CURDATE())
AND MONTH(event_start_date) >= MONTH(CURDATE() - INTERVAL 1 MONTH);
SELECT *
FROM events
WHERE event_start_date >= '1/'+MONTH(DATE_SUB( CURDATE(), INTERVAL 1 MONTH))+'/'+YEAR(DATE_SUB( CURDATE(), INTERVAL 1 MONTH))
For performance, you'd likely want an index range scan operation on the event_start_date column. That means (obviously), you'd want an index with event_start_date as a leading column.
To get an index range scan, the predicate needs to be on the bare event_start_date column, and NOT a function.
WHERE event_start_date >= some_value
For "some_value" in this case, one possible expression you can use would be:
CAST(DATE_FORMAT(NOW()+INTERVAL -1 MONTH ,'%Y-%m-01') AS DATE)
That takes the current date and time, subtracts one month, and then sets the day and time component to midnight of the first of the month.

Returning records from the last 3 months only in MySQL

I have a table with a timestamp field. How do I get data from the last 3 months?
In particular, March is my current month let say, 03/2012. I need to return records from the months March, February, and January only.
3 months before today:
select * from table where timestamp >= now()-interval 3 month;
Start with first of month:
select * from table where timestamp >= last_day(now()) + interval 1 day - interval 3 month;
To get the first day of the current month, you could use this:
DATE_FORMAT(CURDATE(), '%Y-%m-01')
if current date is 2013-03-13, it will return 2013-03-01, and we can just substract 2 months from this date to obtain 2013-01-01. Your query could be like this:
SELECT *
FROM yourtable
WHERE data >= DATE_FORMAT(CURDATE(), '%Y-%m-01') - INTERVAL 2 MONTH
I know this is an old question, but to possibly save others time and to sum the above answers up for the case of needing (1) dates from current month and (2) dates from the prior 2 months (common when displaying data statistics):
WHERE ((timestamp >= NOW() - DATE_FORMAT(CURDATE(), '%Y-%m-01'))
OR (timestamp >= DATE_FORMAT(CURDATE(), '%Y-%m-01') - INTERVAL 2 MONTH))
Assuming you're using SQL Server (Oracle, MySQL and others have similar date functions), you can use the dateadd function to add or subtract an interval to the current date.
If you want a full three months, you can subtract 3 months from today : DATEADD(m,-3,getdate())
But, as you state, you only want data from January, February and March. You have to make some calculation based on today's date: dateadd(m,-2, CONVERT(datetime, CONVERT(VARCHAR(2), MONTH(getdate())) + '/01/' + CONVERT(VARCHAR(4), YEAR(getdate()))))
And in the end, get a query like
SELECT fields
FROM table
WHERE timestampfield > DATEADD(m,-2, CONVERT(datetime, CONVERT(VARCHAR(2), MONTH(getdate())) + '/01/' + CONVERT(VARCHAR(4), YEAR(getdate()))))
--- edit ---
erf, I just noticed the "mysql" tag... you can get more information on MySQL date functions here : https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
Another possibility would be:
SELECT * WHERE your_date_column > LAST_DAY(CURRENT_DATE - INTERVAL 3 MONTH);
Use this code here to get the previous 3 months from a certain date
SELECT * FROM table WHERE date_column>= DATE_FORMAT(current_date(), '%Y-%m-01') - INTERVAL 3 MONTH and date_column< DATE_FORMAT(current_date(), '%Y-%m-01')
WHERE ((timestamp >= NOW() - DATE_FORMAT(CURDATE(), '%Y-%m-01'))
OR (timestamp >= DATE_FORMAT(CURDATE(), '%Y-%m-01') - INTERVAL 2 MONTH))

How to SELECT last calender month (not the interval)?

I have date time field called transaction_date, in a report i need to select last calendar month, how do i do this ? (this should work for a month like January too)
I came up with following but this only works if the month is NOT january,
SELECT SUM(amount) AS pay_month FROM `users_payment` WHERE MONTH(transaction_datetime)= MONTH(NOW()) AND YEAR(transaction_datetime)=YEAR(NOW())
there are lot of examples using INTERVAL functions but this only select the time interval not the calendar month as i wanted too..
like
SELECT SUM(amount) AS `year_month` FROM `users_payment` WHERE DATE_ADD(NOW(), INTERVAL -1 MONTH) < transaction_datetime
but this is not what i want, i want to select sales sum of the DECEMBER only last year (remember there are other years too in the table which i dont want i.e 1979, 1981...etc)
same report next section, i need to select last 2 calender months, I dont know have any idea on how to do this too.
Have you tried the following
SELECT SUM(amount) AS `year_month` FROM `users_payment`
WHERE MONTH(DATE_ADD(NOW(), INTERVAL -1 MONTH)) = MONTH(transaction_datetime)
The above should work to show previous month; it does not distinguish between years however.
On second thought, I see what you are trying to do - To get all the transactions for a given month. Try something like this instead.
SELECT SUM(amount) AS `year_month` FROM `users_payment`
WHERE transaction_datetime BETWEEN date_format(NOW() - INTERVAL 1 MONTH, '%Y-%m-01')
AND last_day(NOW() - INTERVAL 1 MONTH)
This will list all the transactions for the previous calendar month. Alter the INTERVAL values to select multiple months.
You can try this--
SELECT SUM(amount) AS pay_month FROM `users_payment` WHERE
PERIOD_ADD(DATE_FORMAT(NOW(),'%Y%m'), -1) = DATE_FORMAT(transaction_datetime,'%Y%m')

Upcoming birthdays year bug (SQL)

this is my current sql query that gets all the upcoming birthdays for my company in the next 90 days:
SELECT
user.birthday, user.name, MONTH(user.birthday)
AS month, DAY(user.birthday) AS day
FROM user WHERE
(1 =
(FLOOR(DATEDIFF(DATE_ADD(DATE(NOW()),INTERVAL
90 DAY),birthday) / 365.25)) -
(FLOOR(DATEDIFF(DATE(NOW()),birthday)
/ 365.25)))
ORDER BY MONTH(birthday),DAY(birthday)
The problem, is that if right now is november, and there are some birthdays in january, it will display january birthdays first, then november and then december, although january birthdays already happened THIS year.
Is there a way to reorder this records in the same SQL query, so that it displays current and future months first, and THEN next year's months?
First partial solution thanks to Johan
ORDER BY ( MONTH(birthday) > MONTH(NOW()
OR ((MONTH(birthday) = MONTH(now())
AND DAY(birthday) >= DAY(NOW()) DESC
, MONTH(birthday), DAY(birthday)
Still it needs a little improvement. If a birthday already happened, it should be displayed AFTER december on the results. Example of what should be displayed assuming it is 27th june
28 june: john doe
27 december: mary wright
5 june (next year of course): mad max
I'm not sure but it seems that your birthday includes the year. If that's so than you'll have a range of birthdays per user (one for every year) and you can just select the ones within the next 90 days.
SELECT
user.birthday
, user.name
, MONTH(user.birthday) AS month
, DAY(user.birthday) AS day
FROM user
WHERE birthday BETWEEN NOW() AND DATE_ADD(NOW, INTERVAL 90 DAY)
ORDER BY Birthday DESC
If your birthday only has a month and day, your query needs to be:
SELECT
user.birthday
, user.name
, MONTH(user.birthday) AS month
, DAY(user.birthday) AS day
FROM user
WHERE STR_TO_DATE(CONCAT(YEAR(NOW()),MONTH(birthday),DAY(birthday)),'%YYYY%M%D')
BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 90 DAY) OR
STR_TO_DATE(CONCAT(YEAR(DATE_ADD(NOW(),INTERVAL 1 YEAR)),MONTH(birthday),DAY(birthday)),'%YYYY%M%D')
BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 90 DAY)
ORDER BY ( MONTH(birthday) > MONTH(NOW()
OR ((MONTH(birthday) = MONTH(now()) AND DAY(birthday) >= DAY(NOW()) DESC,
MONTH(birthday), DAY(birthday)
I believe you need to order using something that includes the year.
ORDER by date_format( date, "%d/%m/%Y" )
I am no expert but something like this may work too.
ORDER BY YEAR(birthday),MONTH(birthday),DAY(birthday)
I think you want to know if each user's birthday, brought in to the current year or the next year, falls between your range:
SELECT name, birthday
FROM (SELECT name, birthday, YEAR(NOW()) - YEAR(birthday) AS years_ago
FROM user) d
WHERE DATE_ADD(birthday, INTERVAL years_ago YEAR)
BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 90 DAY)
OR
DATE_ADD(birthday, INTERVAL (years_ago + 1) YEAR)
BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 90 DAY);
(It occurs to me that you might actually want INTERVAL 3 MONTH, rather than 90 DAY, expecially if you intend to run this query on the first of every month.)
Your query will create a full table scan.
Store an integer containing the day of the year (1st of april is going to be around 90), and compare that with the current day of the year.
I've been searching for this code, but I couldn't find a clean/simple query (that also works with leap-years (29th of february problem))
So i've made my own.
Here's the simplest code to get the upcoming birthdays for the next x days, (this query also displays the birthdays of yesterday (or you can change it to a x number of days in the past)
SELECT name, date_of_birty
FROM users
WHERE DATE(CONCAT(YEAR(CURDATE()), RIGHT(date_of_birty, 6)))
BETWEEN
DATE_SUB(CURDATE(), INTERVAL 1 DAY)
AND
DATE_ADD(CURDATE(), INTERVAL 5 DAY)