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();
Related
Last year I set up a project management system, but now as we're on a new year I've been bit in my ass by some newbie coding (of me) :)
So now I really need your help to understand how to fix this in a good way once and for all.
The error:
The major problem right now is in the year roll over, right now my SQL query dosn't understand that the month of the new year (1) is larger than the current years (12) which then dosn't show the right projects in the list.
Any ideas? Thanks in advance!
This is my current SQL Query:
SELECT *
FROM projects
WHERE MONTH(CURDATE()) between MONTH(project_start) and MONTH(project_delivery)
AND YEAR(CURDATE()) between YEAR(project_start) and YEAR(project_delivery)
order by project_id
This is the raw structure of the table projects:
Project_id projet_start projet_delivery
1 2018-12-20 2018-12-22
2 2018-12-25 2018-12-29
3 2018-12-28 2018-12-28
4 2018-12-30 2019-01-22
BETWEEN works for actual dates:
SELECT *
FROM projects
WHERE CURDATE() between project_start and project_delivery
order by project_id
If you wanted everything from the month (month granularity) rather than day granularity:
SELECT *
FROM projects
WHERE CURDATE() between DATE_SUB(project_start, INTERVAL DAY(project_start)-1 DAY) and
DATE_ADD(DATE_SUB(project_delivery, INTERVAL DAY(project_delivery) DAY), INTERVAL 1 MONTH)
order by project_id
So if a project started on Dec 5th and finished on Jan 19th, this would give everything between Dec 1st and Jan 31st. Do bear in mind though that if any date on Jan 31st also has a time component (i.e. later than midnight), it will mean it's fractionally after this end date and won't show.
Comment if that's the case and you want help solving it (easiest to not use BETWEEN because it's always inclusive at each end, use < which is exclusive)
Update: Projects that have had some activity this month, i.e a project that:
started before, ended during
started before, ended after
started during, ended during
started during, ended after
The common thing all these have is that the start date of the project is before the end of this month, and also the end date of the project is after the first of this month
SELECT *
FROM projects
WHERE
--started before the end of this month
project_start < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE()) - 1 DAY), INTERVAL 1 MONTH) AND
--ended after the start of this month
project_delivery > DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE()) DAY)
order by project_id
Doing a DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE()) DAY) is a rather convoluted way of writing "subtract the current day number from the current date" i.e. 2019-01-02 minus 2 -> 2018-12-31. We look for dates > this (so as not to include it)
Similarly, DATE_ADD(DATE_SUB(CURDATE(), INTERVAL DAY(CURDATE()) - 1 DAY), INTERVAL 1 MONTH) Takes the current date, subs DAY-1 (so just 1 this time, not 2) off it to reach 1st of this month, then adds a month on to get to first of next month. 2019-01-02 -> 2019-01-01 -> 2019-02-01. Again < it so it's exclusive
There's a bug in going the other way (add a month then sub the day) if you're on eg the 31st of jan and you add a month first - there is no 31st of feb so mysql will cap at 28th of feb, then sub 31 days off it, giving a date that is not the end of jan (i.e. 28th of jan)
Just use date comparisons:
select p.*
from projects p
where curdate() >= project_start and
curdate() <= project_delivery;
I'm not sure why you would want to break the dates into their time components. However, that is totally unnecessary to compare them.
If you want to just do the comparison at the month level, then one method is to convert the values to months:
select p.*
from projects p
where year(curdate()) * 12 + month(curdate()) >= year(project_start) * 12 + month(project_start) and
year(curdate()) * 12 + month(curdate()) <= year(project_delivery) * 12 + month(project_delivery);
Alternatively, just move the dates to the beginning of months:
select p.*
from projects p
where curdate() >= project_start + interval 1 - day(project_start) day and
curdate() < ( project_delivery + interval (1 - day(project_delivery) day) + interval 1 month;
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
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
I m trying to get last 2 and 3 months data.
e.g Last 2 months data means Dec 2014 To Jan 2015 and 3 months means Nov 2014 TO Jan 2015
I tried
SELECT * FROM d_jobs WHERE `job_date` >= DATE_ADD( NOW( ) , INTERVAL -1 MONTH )
Here Its Count last 30 days data only .
So Which is the best way to perform this ?
Try this:
SELECT * FROM d_jobs WHERE `job_date` >= last_day(now()) + interval 1 day - interval 3 month;
Try with this query hope you will overcome your problem i think
select * from d_jobs where job_date < Now() and job_date > DATE_ADD(Now(), INTERVAL- 3 MONTH);
select * from d_jobs where job_date BETWEEN SUBDATE(CURDATE(), INTERVAL 3 MONTH) AND NOW();
select * from d_jobs WHERE job_date BETWEEN STR_TO_DATE('2012-09-01', '%Y-%m-%d') AND NOW();
Get left 7 chars of current date in ISO format (i.e. '2015-01'). Then add "-01" for 1st day of month (result is "2015-01-01"). Then use INTERVAL ... MONTH to get last months.
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)