Get previous 3 months data based on current date - MySQL - mysql

How do I get the previous 3 months data using SQL statement? for example if the current date is 01/01/2012, so how to get the data for December, November, October 2011 ?
Please someone guide me.

SELECT * FROM table1
WHERE mydate BETWEEN DATE_SUB(now(), INTERVAL 3 MONTH) AND now()
Or if you want to stay within the months
SELECT * FROM table1
WHERE MONTH(mydate) BETWEEN MONTH(DATE_SUB(now(), INTERVAL 3 MONTH)) AND MONTH(now())
AND YEAR(mydate) BETWEEN YEAR(DATE_SUB(now(), INTERVAL 3 MONTH)) AND YEAR(now())
This latter version will run much slower, because it cannot use an index for mydate however.

Related

Problem in getting records from last 13 months in MySQL

I am working on to get records from last 13 months using following MySQL query:
SELECT YEAR(`customer_date`),
MONTHNAME(`customer_date`),
COUNT(`customer_date`) AS Enquiries
FROM `crm_customers`
WHERE DATE(`customer_date`) BETWEEN CURRENT_DATE - INTERVAL 13 month AND
CURRENT_DATE
GROUP BY YEAR(`customer_date`),
MONTH(`customer_date`)
ORDER BY YEAR(`customer_date`) DESC,
MONTH(`customer_date`) DESC
My prototype MySQL table crm_customers looks as:
customer_id customer_date
1 2019-02-01 00:00:00
2 2019-02-02 00:00:00
... ...
... ...
... ...
Output:
Though above query does work fine and gives me almost correct result set except one issue related to very last month of the last year from a gap of 13 months from today.
Today is 7th of March 2020. The date condition in my above query
WHERE DATE(`customer_date`) BETWEEN CURRENT_DATE - INTERVAL 13 month AND CURRENT_DATE
starts fetching the result from 7th of Feb 2019.
In the month of Feb, 2019 I have 104 entries. But my above SQL fetches only 80 entries because 24 entries are before 07-Feb-2019 (between 1 Feb and 6 Feb 2019). I want to include those entries as well. How can I modify my date condition to achieve the required result.
EDIT
Why this question is marked negative? I don't understand. Question is very much clear and not duplicated. Is it down voted by GMB?
change your WHERE clause to:
WHERE DATE(`customer_date`) BETWEEN DATE_FORMAT(NOW() ,'%Y-%m-01') - INTERVAL 13 month AND DATE_FORMAT(NOW() ,'%Y-%m-01')
There are some possibility to achieve this
SELECT CURDATE()
, CAST(DATE_FORMAT(NOW() ,'%Y-%m-01') as DATE)
,LAST_DAY(NOW() - INTERVAL 1 MONTH) + INTERVAL 1 DAY;
Results in
CURDATE() , CAST(DATE_FORMAT(NOW() ,'%Y-%m-01') as DATE), LAST_DAY(NOW() - INTERVAL 1 MONTH) + INTERVAL 1 DAY
2020-03-07, 2020-03-01 , 2020-03-01
Sounds like you want to reduce precision in your DATE value. Use EXTRACT() for this;
EXTRACT(YEAR_MONTH FROM CURDATE() - INTERVAL 13 MONTH)
I would suggest:
where
customer_date >= date_format(current_date, '%Y-%m-01') - interval 13 month
and customer_date < current_date + interval 1 day
Rationale:
this compares the stored date without prior transformation (while your query, and all answers so far, use date()), which makes it possible to benefit an existing index - on a large dataset, this can make a big performance difference
date arithmetics is as simple as possible; MySQL happily treats strings in proper formats as dates, which can shorten the syntax

How to show current months projects in list, where current month date is between A and B on new year roll over

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 need to get last three month name in mysql

I need to print previous three month name with this function
SELECT MonthName(CURRENT_DATE()) as month
With this query, I am getting the following :
month
September
I need to show like this it is possible
month
September
August
July
June
Use DATE_SUB to subtract date with the help of interval
SELECT MONTHNAME(DATE_SUB(curdate(), INTERVAL 1 MONTH)) as first, MONTHNAME(DATE_SUB(curdate(), INTERVAL 2 MONTH)) as second, MONTHNAME(DATE_SUB(curdate(), INTERVAL 3 MONTH)) as third
Use DATE_ADD function with MONTH interval -1 thrice to get previous 3 months name. And then use UNION ALL.
Query
select MonthName(CURRENT_DATE()) as month
union all
select MonthName(DATE_ADD(CURRENT_DATE(), INTERVAL -1 MONTH))
union all
select MonthName(DATE_ADD(CURRENT_DATE(), INTERVAL -2 MONTH))
union all
select MonthName(DATE_ADD(CURRENT_DATE(), INTERVAL -3 MONTH));

MySQL Query to get all rows for 2 months ago

I need to do a select where I can chose to see results for current month, previous month, 1 month ago, 2 months ago, 3 months ago.
I found this question: MySQL: Query to get all rows from previous month, but I'm stuck with a filter that will get me all the results for 2 months ago from first to last day of the month.
I tried with this but it doesn't work:
SELECT * FROM table
AND MONTH(date_created) = MONTH(1 MONTH - INTERVAL 2 MONTH);
Try this:
SELECT * FROM table
WHERE MONTH(date_created) = MONTH(NOW() - INTERVAL 2 MONTH)
AND (
YEAR(date_created) = YEAR(NOW())
OR
YEAR(date_created) = YEAR(NOW() - INTERVAL 2 MONTH)
);
Returning records CREATED PRIOR the last 2 months only in MySQL.
If you want all rows from 2 months ago, then use logic like this:
WHERE date_created >= DATE_SUB(DATE_SUB(CURDATE(), 1 - DAY(CURDATE())), INTERVAL 2 MONTH) AND
date_created < DATE_SUB(DATE_SUB(CURDATE(), 1 - DAY(CURDATE())), INTERVAL 1 MONTH)
What is this doing? First, it is only applying functions to the current date part of the expression. This allows MySQL to use an index on date_created, if available and appropriate.
The expression DATE_SUB(CURDATE(), 1 - DAY(CURDATE()) is simply a way to get the first day of the month.
You query have an error, correct one would be:
SELECT * FROM table
WHERE MONTH(date_created) = MONTH(DATE_SUB(NOW(),INTERVAL 2 MONTH))
For current month just MONTH(NOW()), replace "2" with any number of months you need (1,3,.. 23)
as mentioned in comments this solution ignores YEAR differences, it just selects all records with the same month, no matter the year
you can filter wrong year results with additional clause:
AND YEAR(date_created) = '2019' # or year you need
Or use more complex query:
SELECT * FROM table
where
date_created between
/* first day of -2 month*/
date_sub(date_sub(now(),interval 2 month), interval (day(now())-1) day)
and
/* last day of -2 month*/
last_day(date_sub(now(),interval 2 month))

MySQL - order by one month from today

How to order records by one month from today. I have tried the following but it does not work.
WHERE MONTH(date) = MONTH(CURDATE() -1 month)
Do you mean this? This will get you everything in your table where the month of the date field is equal to the current month - 1:
WHERE MONTH(date) = month(curdate() - interval 1 month)
WHERE MONTH(date) = MONTH(CURDATE() - INTERVAL 1 MONTH)
Hard to tell what you're after from your question, so I'm taking a punt that you want to show records that have the date that is exactly one month from now
SELECT *
FROM yourtable
WHERE MONTH(date) = MONTH(DATE_SUB(CURDATE(), INTERVAL 1 MONTH))
That will get all entries for October, if we are currently in November.
If you want it down to the day, so if today is November 20 you want to grab items from October 20, you'll need something like this
SELECT *
FROM agentjobsets
WHERE DATE(created_at) = DATE_SUB(CURDATE(), INTERVAL 1 MONTH)