sql query add 1 year, less days passed in month - mysql

I have a table with rows of dates,
I need to get rows for one year:
SELECT DATE_FORMAT(cal_date, '%e %M') as cal_date, price_client,
price_owner, description FROM table WHERE cal_date <
DATE_ADD('2017-09-13' , INTERVAL 1 year)
The result of this query are date rows with dates from 1 September 2017 until 12 September 2018.
I would like the result from 13 September 2017 until 12 September 2018.
Updated, This is the correct query, works like I wanted:
WHERE cal_date >= '2017-09-13' and cal_date < DATE_ADD('2017-09-13' ,
INTERVAL 1 year)

for a generic format based on curdate() you could use
SELECT
DATE_FORMAT(cal_date, '%e %M') as cal_date
, price_client
, price_owner
, description
FROM table WHERE cal_date <
DATE_ADD(DATE_ADD(LAST_DAY(DATE_SUB(CURDATE(), interval 30 day), interval 1 day) ,
INTERVAL 1 year)

Seems to work once you account for cal_date>= same date
you handled < future date but you didn't handle > or >= current date. As it stands you will always return all records older than 1 year from today. you have no lower boundary defined.
DEMO: http://rextester.com/WDXHE5921
SELECT DATE_FORMAT(cal_date, '%e %M%Y') as cal_date, price_client,
price_owner, description
FROM table
WHERE cal_date < DATE_ADD('2017-09-13' , INTERVAL 1 year)
and cal_date >= '2017-09-13';
This question would have benefited from talking to the duck first

Related

Is it possible to create a single sql statement to fetch a list of people where their birthday celebration will fall in next 60 days

I have a table where it has some name and dateofbirth.
Refence data:
ABC, 1990-11-23
BCD, 1998-10-21
CDE, 1997-05-02
DEF, 2000-10-15
EFG, 1999-01-10
FGH, 1987-01-15
GHI, 1989-12-19
HIJ, 1986-12-09
I need a SQL query where I need to get the birthday celebration dates that is going to happen during the next 60 days ordered by celebration dates.
This is the query that I used till now.
SELECT *
FROM `friends`
WHERE ( DATE_FORMAT(`dob`, '%m%d') >= DATE_FORMAT(CURDATE(), '%m%d')
AND DATE_FORMAT(`dob`, '%m%d') <= DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 60 DAY), '%m%d')
ORDER BY DATE_FORMAT(`dob`, '%m%d');
It works ok if it runs during Jan to Oct. During November and December, the condition DATE_FORMAT(dob, '%m%d') <= DATE_FORMAT(DATE_ADD(CURDATE(), INTERVAL 60 DAY), '%m%d') cannot apply. For example, the resulting comparison will be like 1209 < 0131 and fails.
The result that I expect to get when executed on Dec 2, 2022 is
HIJ, 1986-12-09
GHI, 1989-12-19
EFG, 1999-01-10
FGH, 1987-01-15
How do I do this in one single query?
The thread mentioned in the comment to your question uses things like adding 365.25 days to get this to work. I think this solution might be more reliable.
You can construct this years' birthday by extracting the month and day from the date of birth, and concatenating the current year to it using STR_TO_DATE.
Then you can check using a CASE statement if this years' birthday has already passed, in which case you add a year to that birthday, because that will be the next birthday for name. Then you can check if the result of that CASE statement is BETWEEN today and 60 days from now.
I used a CTE to make it clearer to read. DBfiddle here.
WITH cte as (
SELECT
-- First determine this years (year of current date) birthday
-- by constructing it from the current year, month of birth and day of birth
STR_TO_DATE(
CONCAT(YEAR(CURDATE()),'-', MONTH(dob), '-', DAY(dob)),
'%Y-%m-%d') AS this_years_birthday,
name,
dob
FROM friends
)
SELECT cte.name, cte.dob
FROM cte
WHERE
-- If the birthday is still in this year
-- Use this years' birthday
-- else add a year to this years' birthday
-- Then filter it to be between today and 60 days from now
CASE WHEN this_years_birthday >= CURDATE()
THEN this_years_birthday
ELSE DATE_ADD(this_years_birthday, INTERVAL 1 YEAR) END
BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 60 DAY)
ORDER BY MONTH(cte.dob) DESC
name
dob
GHI
1989-12-19
HIJ
1986-12-09
EFG
1999-01-10
FGH
1987-01-15

How do i select all records for the next 3 months including the current one when it turns into a new year

I am trying to select every record between current month and the next 2 months but I am not able to because the year will be changing from 2016 to 2017.
For ex.
I want to get all the records from November 2016 to January 2017.
The current query (shown below) i have has worked fine until this month because November 2016 + 2 months = Jan 2017.
select * from dateTable
where month(t2.`END_DATE`) between month(curdate()) and
month(DATE_ADD(curdate(), INTERVAL 2 MONTH))
and year(t2.`END_DATE`) = year(curdate());
This returns 0 rows because this cannot handle having two years, 2016 and 2017.
How would I go about doing this?
This should be what you need, although there are probably a number of ways of doing this
select * from dateTable
where `END_DATE` BETWEEN DATE_FORMAT(NOW() ,'%Y-%m-01')
AND LAST_DAY(DATE_ADD(NOW(), INTERVAL 2 MONTH))
The result of this query will demonstrate the dates being generated
SELECT DATE_FORMAT(NOW() ,'%Y-%m-01') as from_date,
LAST_DAY(DATE_ADD(NOW(), INTERVAL 2 MONTH)) as to_date
Today this will generate
from_date to_date
2016-11-01 2017-01-31
Try to use full datetime with DATE_ADD and DATE_DIFF functions.
select * from dateTable where t2.`END_DATE`
between DATEADD(month,
DATEDIFF(month, 0, getdate() -- get difference to first day
), 0)
and DATEADD(month, 2, -- add 3 months interval to get first day of third
DATEADD(month,
DATEDIFF(month, 0, getdate() -- get difference to first day
), 0))
If you have to remove the first day from last month use DATEADD again and remove 1 second to get 23:59:59

Mysql date_sub interval 12 month

I'm trying to get all posts from the 12 last month, group by month. I have a quite correct query:
SELECT MONTH(time) as mois, YEAR(time) as annee, count(*) as nbre
FROM touist_stories
WHERE time >= DATE_SUB(now() + INTERVAL 1 MONTH, INTERVAL 2 YEAR)
group by MONTH(time)
order by YEAR(time) DESC, MONTH(time) DESC
But one month is always missing : november 2012
I tryied to add
+ INTERVAL 1 MONTH
to now() but it still missing... How can I get the 12 last month and not the 11 ones please?
Thanks
To get one year ago, here's a technique I've used in the past. Using #mysql variables, create a date based on the first day of a given month/year (via now()), then subtract 12 months. This example will get from Oct 1, 2012 to current -- which will include current Oct 2013. To exclude that, just add to where clause where I re-added 1 year so it goes from Oct 1, 2012 at 12:00:00 am to LESS THEN Oct 1, 2013 12:00:00.
SELECT
MONTH(time) as mois,
YEAR(time) as annee,
count(*) as nbre
FROM
touist_stories,
( select #lastYear := date_add( DATE_FORMAT(NOW(),
'%Y-%m-01'), interval -11 month) ) sqlvar
WHERE
time >= #lastYear
group by
MONTH(time)
order by
YEAR(time) DESC,
MONTH(time) DESC
Revised to make it go 11 months back (to November per example), and include UP TO AND INCLUDING all Current October activity.
For realy want on year data use 11 MONTH not 12
SELECT time
FROM touist_stories
WHERE time
BETWEEN
date_sub(Now(), INTERVAL 11 MONTH)
AND
Now();

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

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)