MySQL: receive data only per months - mysql

Few times ago, I asked how to do to display data per month, I must told a bad explanation because I just figured out that it's not what I want :
Here's what I got :
$req1 = ...
AND v.date > (DATE_SUB(CURDATE(), INTERVAL 2 MONTH))
AND v.date < (DATE_SUB(CURDATE(), INTERVAL 1 MONTH))
$req2= ...
AND v.date > (DATE_SUB(CURDATE(), INTERVAL 3 MONTH))
AND v.date < (DATE_SUB(CURDATE(), INTERVAL 2 MONTH))
But the problem, imagine that today you are the 10th June, it's going to calculate ALL the data between the
10 june to the 10 may
then the 10 may until the 10 april...
But what I want is data :
from 1st may to 1 st june,
from 1st june to 1st july...
Do you see what I mean ?

You could use:
WHERE YEAR(date) = 2010 AND MONTH(date) = 5
to get all rows where date is in the YEAR 2010 and the fifth month of the year.

AND MONTH(v.date)=6 AND YEAR(v.date)=2009 [to get everything in June 2009]

select month(v.date), year(v.date), sum(somedatacolumn) from thetable group by month(v.date), year(v.date);
replace sum with whatever calculation you are doing

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

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

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)

Get previous 3 months data based on current date - 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.

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)