Generate report by month and year in mysql - mysql

I need to generate a report 12 months before the current date.
Today is 2014-04-29. So my date range would be 2013-04-29 to 2014-04-29.
These is my sample data:
--------------------------------------
-- user_id | lead_id | date_entered --
-- 1 | 1 | 2013-12-05 --
-- 1 | 2 | 2014-03-15 --
-- 1 | 3 | 2014-04-24 --
--------------------------------------
Expected output should be:
--------------------------
-- month | year | total --
-- Apr | 2013 | 0 --
-- May | 2013 | 0 --
-- Jun | 2013 | 0 --
-- Jul | 2013 | 0 --
-- Aug | 2013 | 0 --
-- Sep | 2013 | 0 --
-- Oct | 2013 | 0 --
-- Nov | 2013 | 0 --
-- Dec | 2013 | 1 --
-- Jan | 2014 | 0 --
-- Feb | 2014 | 0 --
-- Mar | 2014 | 1 --
-- Apr | 2014 | 1 --
--------------------------
Here is my query:
select a.month, a.year, IFNULL(d.total, 0) AS total
from (
SELECT 'Apr' month, 2013 year, 1 monthOrder UNION
SELECT 'May' month, 2013 year, 2 monthOrder UNION
SELECT 'Jun' month, 2013 year, 3 monthOrder UNION
SELECT 'Jul' month, 2013 year, 4 monthOrder UNION
SELECT 'Aug' month, 2013 year, 5 monthOrder UNION
SELECT 'Sep' month, 2013 year, 6 monthOrder UNION
SELECT 'Oct' month, 2013 year, 7 monthOrder UNION
SELECT 'Nov' month, 2013 year, 8 monthOrder UNION
SELECT 'Dec' month, 2013 year, 9 monthOrder UNION
SELECT 'Jan' month, 2014 year, 10 monthOrder UNION
SELECT 'Feb' month, 2014 year, 11 monthOrder UNION
SELECT 'Mar' month, 2014 year, 12 monthOrder UNION
SELECT 'Apr' month, 2014 year, 13 monthOrder
) AS a left join (
SELECT date_entered, count(id) AS total
FROM leads AS b
WHERE user_id = 1
AND is_deleted = 0
AND date_entered BETWEEN "2013-04-29" AND "2014-04-29"
GROUP BY YEAR(b.date_entered), MONTH(b.date_entered)
) AS d on a.month = DATE_FORMAT(d.date_entered, "%b")
ORDER BY a.monthOrder asc
My query's output:
--------------------------
-- month | year | total --
-- Apr | 2013 | 1 --
-- May | 2013 | 0 --
-- Jun | 2013 | 0 --
-- Jul | 2013 | 0 --
-- Aug | 2013 | 0 --
-- Sep | 2013 | 0 --
-- Oct | 2013 | 0 --
-- Nov | 2013 | 0 --
-- Dec | 2013 | 1 --
-- Jan | 2014 | 0 --
-- Feb | 2014 | 0 --
-- Mar | 2014 | 1 --
-- Apr | 2014 | 1 --
--------------------------
Because on my on a.month = DATE_FORMAT(d.date_entered, "%b") I compare the month that's why Apr 2013 has a total 1. How do I fix this issue? Can someone help me?
is there a way I can compare both month and year? How do I do that?
Thanks

I think you should simplify and use this hack...
basically you format the date in year/month format and group by it as a string, and count.
This query alone should give you all the report you need.
select
concat( DATE_FORMAT(date_entered ,'%Y%m')) as `yearmonth`,
count(*) as `total`
from
leads
where
user_id=1 and
is_deleted = 0 and
date_entered BETWEEN "2013-04-29" AND "2014-04-29"
group by 1
order by date_entered
Try it and tune it according to your needs.
Do not add other columns because it will group by those too and you will get wrong results.

You need to query year on grouping too, using WHERE a.year=DATE_FORMAT(d.date_entered, "%Y") as extra condition at top select level.
select a.month, a.year, IFNULL(d.total, 0) AS total
from (
SELECT 'Apr' month, 2013 year, 1 monthOrder UNION
SELECT 'May' month, 2013 year, 2 monthOrder UNION
SELECT 'Jun' month, 2013 year, 3 monthOrder UNION
SELECT 'Jul' month, 2013 year, 4 monthOrder UNION
SELECT 'Aug' month, 2013 year, 5 monthOrder UNION
SELECT 'Sep' month, 2013 year, 6 monthOrder UNION
SELECT 'Oct' month, 2013 year, 7 monthOrder UNION
SELECT 'Nov' month, 2013 year, 8 monthOrder UNION
SELECT 'Dec' month, 2013 year, 9 monthOrder UNION
SELECT 'Jan' month, 2014 year, 10 monthOrder UNION
SELECT 'Feb' month, 2014 year, 11 monthOrder UNION
SELECT 'Mar' month, 2014 year, 12 monthOrder UNION
SELECT 'Apr' month, 2014 year, 13 monthOrder
) AS a left join (
SELECT date_entered, count(id) AS total
FROM leads AS b
WHERE user_id = 1
AND is_deleted = 0
AND date_entered BETWEEN "2013-04-29" AND "2014-04-29"
GROUP BY YEAR(b.date_entered), MONTH(b.date_entered)
) AS d on a.month = DATE_FORMAT(d.date_entered, "%b")
WHERE a.year=DATE_FORMAT(d.date_entered, "%Y") -- this added
ORDER BY a.monthOrder asc
Or use AND instead of WHERE, this should have the same effectm as proposed in comments. on a.month = DATE_FORMAT(d.date_entered, "%b") AND a.year=DATE_FORMAT(d.date_entered, "%Y")

You can match 2 fields with join as per below:
SELECT a.month, a.year, IFNULL(d.total, 0) AS total
FROM (
SELECT 'Apr' MONTH, 2013 YEAR, 1 monthOrder UNION
SELECT 'May' MONTH, 2013 YEAR, 2 monthOrder UNION
SELECT 'Jun' MONTH, 2013 YEAR, 3 monthOrder UNION
SELECT 'Jul' MONTH, 2013 YEAR, 4 monthOrder UNION
SELECT 'Aug' MONTH, 2013 YEAR, 5 monthOrder UNION
SELECT 'Sep' MONTH, 2013 YEAR, 6 monthOrder UNION
SELECT 'Oct' MONTH, 2013 YEAR, 7 monthOrder UNION
SELECT 'Nov' MONTH, 2013 YEAR, 8 monthOrder UNION
SELECT 'Dec' MONTH, 2013 YEAR, 9 monthOrder UNION
SELECT 'Jan' MONTH, 2014 YEAR, 10 monthOrder UNION
SELECT 'Feb' MONTH, 2014 YEAR, 11 monthOrder UNION
SELECT 'Mar' MONTH, 2014 YEAR, 12 monthOrder UNION
SELECT 'Apr' MONTH, 2014 YEAR, 13 monthOrder
) AS a LEFT JOIN (
SELECT date_entered, COUNT(id) AS total
FROM leads AS b
WHERE user_id = 1
AND is_deleted = 0
AND date_entered BETWEEN "2013-04-29" AND "2014-04-29"
GROUP BY YEAR(b.date_entered), MONTH(b.date_entered)
) AS d ON a.month = DATE_FORMAT(d.date_entered, "%b") AND a.YEAR = DATE_FORMAT(d.date_entered, "%Y")
ORDER BY a.monthOrder ASC

Related

Add dates of one whole month in mysql database

Can Any one please tell me how to add one whole month date's in mysql database. For now I'm adding one date at a time.
This query generates all the days of a given month.
I found this in this post.
When you change NOW() function with any date you want, it generates the dates of that month. You can also join this with your queries or you can use it with INSERT [(col_name,...)] SELECT ... statement to insert all the dates to a table.
SELECT date_field
FROM
(
SELECT
MAKEDATE(YEAR(NOW()),1) +
INTERVAL (MONTH(NOW())-1) MONTH +
INTERVAL daynum DAY date_field
FROM
(
SELECT t*10+u daynum
FROM
(SELECT 0 t UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) A,
(SELECT 0 u UNION SELECT 1 UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7
UNION SELECT 8 UNION SELECT 9) B
ORDER BY daynum
) AA
) AAA
WHERE MONTH(date_field) = MONTH(NOW());
plan
build up decimal numbers with cross join on digits - all numbers can be expressed as :
an10^n + .. a0*10^0
use date_add to add start of month data filtering where less than next month start
setup
create table example
(
`date` date primary key not null
);
drop view if exists digits_v;
create view digits_v
as
select 0 as n
union all
select 1 union all select 2 union all select 3 union all
select 4 union all select 5 union all select 6 union all
select 7 union all select 8 union all select 9
;
query
insert into example ( `date` )
select date_add(date('2015-11-01'), interval a2.n * 100 + a1.n * 10 + a0.n day)
from digits_v a2
cross join digits_v a1
cross join digits_v a0
where date_add(date('2015-11-01'), interval a2.n * 100 + a1.n * 10 + a0.n day)
< date('2015-12-01')
;
sqlfiddle
selecting the top 10 gives
select `date`
from example
order by `date`
limit 10
;
.
+----------------------------+
| date |
+----------------------------+
| November, 01 2015 00:00:00 |
| November, 02 2015 00:00:00 |
| November, 03 2015 00:00:00 |
| November, 04 2015 00:00:00 |
| November, 05 2015 00:00:00 |
| November, 06 2015 00:00:00 |
| November, 07 2015 00:00:00 |
| November, 08 2015 00:00:00 |
| November, 09 2015 00:00:00 |
| November, 10 2015 00:00:00 |
+----------------------------+

MySQL monthly Sale of last 12 months including months with no Sale

SELECT DATE_FORMAT(date, "%b") AS month, SUM(total_price) as total
FROM cart
WHERE date <= NOW()
and date >= Date_add(Now(),interval - 12 month)
GROUP BY DATE_FORMAT(date, "%m-%Y")
This query displaying result for only existing month. I need all 12 months sales.
Output:
"month" "total"
--------------
"Jun" "22"
"Aug" "30"
"Oct" "19"
"Nov" "123"
"Dec" "410"
Required Output:
"month" "total"
--------------
"Jan" "0"
"Feb" "0"
"Mar" "0"
"Apr" "0"
"May" "0"
"Jun" "22"
"Jul" "0"
"Aug" "30"
"Sep" "0"
"Oct" "19"
"Nov" "123"
"Dec" "410"
Consider the following table
mysql> select * from cart ;
+------+------------+-------------+
| id | date | total_price |
+------+------------+-------------+
| 1 | 2014-01-01 | 10 |
| 2 | 2014-01-20 | 20 |
| 3 | 2014-02-03 | 30 |
| 4 | 2014-02-28 | 40 |
| 5 | 2014-06-01 | 50 |
| 6 | 2014-06-13 | 24 |
| 7 | 2014-12-12 | 45 |
| 8 | 2014-12-18 | 10 |
+------+------------+-------------+
Now as per the logic you are looking back one year and december will appear twice in the result i.e. dec 2013 and dec 2014 and if we need to have a separate count for them then we can use the following technique of generating dynamic date range MySql Single Table, Select last 7 days and include empty rows
t1.month,
t1.md,
coalesce(SUM(t1.amount+t2.amount), 0) AS total
from
(
select DATE_FORMAT(a.Date,"%b") as month,
DATE_FORMAT(a.Date, "%m-%Y") as md,
'0' as amount
from (
select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a
where a.Date <= NOW() and a.Date >= Date_add(Now(),interval - 12 month)
group by md
)t1
left join
(
SELECT DATE_FORMAT(date, "%b") AS month, SUM(total_price) as amount ,DATE_FORMAT(date, "%m-%Y") as md
FROM cart
where Date <= NOW() and Date >= Date_add(Now(),interval - 12 month)
GROUP BY md
)t2
on t2.md = t1.md
group by t1.md
order by t1.md
;
Output will be
+-------+---------+-------+
| month | md | total |
+-------+---------+-------+
| Jan | 01-2014 | 30 |
| Feb | 02-2014 | 70 |
| Mar | 03-2014 | 0 |
| Apr | 04-2014 | 0 |
| May | 05-2014 | 0 |
| Jun | 06-2014 | 74 |
| Jul | 07-2014 | 0 |
| Aug | 08-2014 | 0 |
| Sep | 09-2014 | 0 |
| Oct | 10-2014 | 0 |
| Nov | 11-2014 | 0 |
| Dec | 12-2013 | 0 |
| Dec | 12-2014 | 55 |
+-------+---------+-------+
13 rows in set (0.00 sec)
And if you do not care about the above case i.e. dec 2014 and dec 2013
Then just change the group by in dynamic date part as
where a.Date <= NOW() and a.Date >= Date_add(Now(),interval - 12 month)
group by month
and final group by as group by t1.month
Thanks for #pankaj hint, Here i resolved it via this query...
SELECT
SUM(IF(month = 'Jan', total, 0)) AS 'Jan',
SUM(IF(month = 'Feb', total, 0)) AS 'Feb',
SUM(IF(month = 'Mar', total, 0)) AS 'Mar',
SUM(IF(month = 'Apr', total, 0)) AS 'Apr',
SUM(IF(month = 'May', total, 0)) AS 'May',
SUM(IF(month = 'Jun', total, 0)) AS 'Jun',
SUM(IF(month = 'Jul', total, 0)) AS 'Jul',
SUM(IF(month = 'Aug', total, 0)) AS 'Aug',
SUM(IF(month = 'Sep', total, 0)) AS 'Sep',
SUM(IF(month = 'Oct', total, 0)) AS 'Oct',
SUM(IF(month = 'Nov', total, 0)) AS 'Nov',
SUM(IF(month = 'Dec', total, 0)) AS 'Dec',
SUM(total) AS total_yearly
FROM (
SELECT DATE_FORMAT(date, "%b") AS month, SUM(total_price) as total
FROM cart
WHERE date <= NOW() and date >= Date_add(Now(),interval - 12 month)
GROUP BY DATE_FORMAT(date, "%m-%Y")) as sub
Month wise sale
Use Count to count month wise data.
SELECT DATE_FORMAT(date, "%b") AS month, COUNT(total_price) as total
FROM cart
WHERE date <= NOW()
and date >= Date_add(Now(),interval - 12 month)
GROUP BY DATE_FORMAT(date, "%m-%Y")

SQL Server Duplication and correct assignment of Joins

I want the resulting table to be like the example Table I have provided, even though the only month provided was 5, I want the table to display all the 12 months even if the Amount was to be 0 for the other months.
This is the query I'm using,
Select Distinct T1.EmployeeID, T1.Name, T.MonthID, T1.TotalAmount, T1.TotalQuantity From
(Select
S.EmployeeID,
E.Name,
YEAR(MAX([Date])) As [Year],
MONTH(MAX([Date])) As [Montht],
IsNull(SUM(Amount), 0) As TotalAmount,
IsNull(SUM(Quantity), 0) As TotalQuantity
From Sales S Inner Join Employee E On E.EmployeeID = S.EmployeeID
Group By
S.EmployeeID,
E.Name,
YEAR([Date]),
MONTH([Date])) As T1
Inner Join
(Select 'January' as Month , 1 as MonthID
UNION select 'February' as Month , 2 as MonthID
UNION select 'March' as Month , 3 as MonthID
UNION select 'April' as Month , 4 as MonthID
UNION select 'May' as Month , 5 as MonthID
UNION select 'June' as Month , 6 as MonthID
UNION select 'July' as Month , 7 as MonthID
UNION select 'August' as Month , 8 as MonthID
UNION select 'September' as Month , 9 as MonthID
UNION select 'October' as Month , 10 as MonthID
UNION select 'November' as Month , 11 as MonthID
UNION select 'December' as Month , 12 as MonthID) As T
On T1.Montht <> T.MonthID
Where T.MonthID Not In
(Select
MONTH(MAX([Date])) As [Montht]
From Sales S Inner Join Employee E
On E.EmployeeID = S.EmployeeID And E.EmployeeID = 1
Group By S.EmployeeID,
E.Name,
YEAR([Date]),
MONTH([Date]))
Order By T1.Name
Employee Table (Example, not full table),
+--+--+------+
|ID| Name |
+--+---------+
|1 |John Doe |
+--+---------+
|2 |Jane Doe |
+--+---------+
Sales Table (Example, not full table),
+--+------+---------+-------+--------+
|ID|SaleID| Date |Amount |Quantity|
+--+------+---------+-------+--------+
|1 | 1 |5-14-2014|300 |12 |
+--+------+---------+-------+--------+
|1 | 2 |5-16-2014|600 |4 |
+--+------+---------+-------+--------+
|2 | 3 |5-14-2014|452 |10 |
+--+------+---------+-------+--------+
|2 | 4 |5-16-2014|356 |2 |
+--+------+---------+-------+--------+
I'm getting this result,
http://i61.tinypic.com/xnumpz.png
The problem with that result is the duplication, and that those 3 values (The ones duplicating) are only suppose to be displayed on the 4, 5, 6
Like so,
+-------+-----------+
|MonthID|TotalAmount|
+-------+-----------+
|4 |757.00 |
+-------+-----------+
|5 |834.00 |
+-------+-----------+
|6 |880.00 |
+-------+-----------+
While since the other months would have a value of 0.
I ended up using a Pivot which solved my problem in a magnificent way, this is for anyone with the same problem looking around.
Declare #Year As Int
Set #Year = 2014
Select [Employee ID], Name, #Year As [Year],
IsNull(January, 0) As January, IsNull(February, 0) As February, IsNull(March, 0) As March,
IsNull(April, 0) As April, IsNull(May, 0) As May, IsNull(June, 0) As June,
IsNull(July, 0) As July, IsNull(August, 0) As August, IsNull(September, 0) As September,
IsNull(October, 0) As October, IsNull(November, 0) As November, IsNull(December, 0) As December
From
(Select
S.EmployeeID As [Employee ID],
E.Name,
YEAR([Date]) As [Year],
DATENAME(MONTH, [Date]) As [Month],
IsNull(SUM(Amount), 0) As TotalAmount
From Sales S Left Outer Join Employee E
On S.EmployeeID = E.EmployeeID
Group By
S.EmployeeID,
E.Name,
YEAR([Date]),
DATENAME(MONTH, [Date])) As MonthlySale
Pivot(SUM(TotalAmount)
For Month In ([January], [February], [March],
[April], [May], [June],
[July], [August], [September],
[October], [November], [December])) As MyPivot

quarter year wise filteration in sql

I have a table having structure as follows
id cust_id target month year fiscal_ID
1 234 50 4 2013 1
2 234 50 5 2013 1
3 234 50 6 2013 1
4 234 150 7 2013 1
5 234 150 8 2013 1
6 234 150 9 2013 1
I need to get the result as follows
cust_id target quarter year fiscal_ID
234 150 Q1 2013 1
234 450 Q2 2013 1
months 4,5,6 in Q1, 7,8,9 in Q2 etc
Since you are storing the month and year in separate columns, one way you can get the result is to use a derived table that references the month and quarter and you join to that data:
select t.cust_id,
sum(target) target,
d.qtr,
t.year,
t.fiscal_id
from yourtable t
inner join
(
select 4 mth, 'Q1' qtr union all
select 5 mth, 'Q1' qtr union all
select 6 mth, 'Q1' qtr union all
select 7 mth, 'Q2' qtr union all
select 8 mth, 'Q2' qtr union all
select 9 mth, 'Q2'
) d
on t.month = d.mth
group by t.cust_id, d.qtr, t.year, t.fiscal_id;
See SQL Fiddle with Demo.

how i can get these with mysql?

I am new to mysql.
I have on survey with clicks, period(date). Now i have to find out number of clicks per month, like:
MON CLICKS
nov 0
oct 34
sep 67
aug 89
I have used code like this:
select MONTHNAME(period) mon, IFNULL(count(id),0) as Clicks
from survey
where period > DATE_SUB(now(), INTERVAL 3 MONTH)
group by EXTRACT(MONTH FROM period)
It is not working for with no records.
Here one thing I suppose there is no record in that month it should show 0: if there is no record in nov the number of clicks should be 0.
my table structure was like this
CREATE TABLE `survey` (
`id` int(2) NOT NULL auto_increment,
`period` datetime default NULL)
for last four weeks i have used
SELECT uq.timespan, COALESCE(tsq.TotalClicks, 0) as Clicks FROM (
SELECT '22-28 days' as timespan
union SELECT '15-21 days'
union SELECT '8-14 days'
union SELECT 'up to 7 days'
)uq LEFT JOIN (
SELECT CASE
WHEN submitdate >= NOW() - INTERVAL 4 WEEK
AND submitdate < NOW() - INTERVAL 3 WEEK THEN '22-28 days'
WHEN submitdate >= NOW() - INTERVAL 3 WEEK
AND submitdate < NOW() - INTERVAL 2 WEEK THEN '15-21 days'
WHEN submitdate >= NOW() - INTERVAL 2 WEEK
AND submitdate < NOW() - INTERVAL 1 WEEK THEN '8-14 days'
WHEN submitdate >= NOW() - INTERVAL 1 WEEK THEN 'up to 7 days'
END Weeksubmitdate,
count(id) TotalClicks
FROM survey
WHERE submitdate >= NOW() - INTERVAL 4 WEEK
GROUP BY Weeksubmitdate
)tsq ON uq.timespan = tsq.Weeksubmitdate
Any help?
I usually do Pivot table to achieve this. Assuming your click information is stored into a table named SURVEY and assuming only the date/time of the click is stored into one column of the SURVEY table (which is all what you need) then here is one way to do it:
select year(period),
sum(case when month(period)=1 then 1 else 0 end) jan,
sum(case when month(period)=2 then 1 else 0 end) feb,
sum(case when month(period)=3 then 1 else 0 end) mar,
sum(case when month(period)=4 then 1 else 0 end) apr,
sum(case when month(period)=5 then 1 else 0 end) may,
sum(case when month(period)=6 then 1 else 0 end) jun,
sum(case when month(period)=7 then 1 else 0 end) jul,
sum(case when month(period)=8 then 1 else 0 end) aug,
sum(case when month(period)=9 then 1 else 0 end) sep,
sum(case when month(period)=10 then 1 else 0 end) oct,
sum(case when month(period)=11 then 1 else 0 end) nov,
sum(case when month(period)=11 then 1 else 0 end) dec
from survey
group by year(period)
The output is something like:
---------------------------------------------------------------------------------
| Year | JAN | FEB | MAR | APR | MAY | JUN | JUL | AUG | SEP | OCT | NOV | DEC |
---------------------------------------------------------------------------------
| 2012 | 5 | 20 | 13 | 0 | 0 | 65 | 15 | 0 | 0 | 21 | 0 | 0 |
---------------------------------------------------------------------------------
I even set up the same Fiddle SQL for you
SQL Fiddle Demo
An alternative way (Column based for the last 4 months even with ZERO count):
SQL Fiddle Demo
SELECT mon,
sum(clicks) clicks
FROM ( SELECT month(period) mnth,
date_format(period,'%b') mon,
count(1) clicks
FROM survey
WHERE month(period) BETWEEN month(curdate()) - 4 AND month(curdate())
GROUP BY 1, 2
UNION ALL
SELECT 1 mnth, 'Jan' mon, 0 clicks
UNION ALL
SELECT 2 mnth, 'Feb' mon, 0 clicks
UNION ALL
SELECT 3 mnth, 'Mar' mon, 0 clicks
UNION ALL
SELECT 4 mnth, 'Apr' mon, 0 clicks
UNION ALL
SELECT 5 mnth, 'May' mon, 0 clicks
UNION ALL
SELECT 6 mnth, 'Jun' mon, 0 clicks
UNION ALL
SELECT 7 mnth, 'Jul' mon, 0 clicks
UNION ALL
SELECT 8 mnth, 'Aug' mon, 0 clicks
UNION ALL
SELECT 9 mnth, 'Sep' mon, 0 clicks
UNION ALL
SELECT 10 mnth, 'Oct' mon, 0 clicks
UNION ALL
SELECT 11 mnth, 'Nov' mon, 0 clicks
UNION ALL
SELECT 12 mnth, 'Dec' mon, 0 clicks) a
WHERE mnth BETWEEN month(curdate()) - 4 AND month(curdate())
GROUP BY 1
ORDER BY mnth
You need to join to a table that contains all month names. Here's one way to do it:
select
mon,
ifnull(count(id), 0) as Clicks
from (select 'nov' as mon union select 'oct' union select 'sep' union select 'aug') m
left join survey on MONTHNAME(period) = mon
where submitdate > DATE_SUB(now(), INTERVAL 3 MONTH)
group by 1
select MONTHNAME(STR_TO_DATE(month(period), '%m'))as 'month',count(*) as clicks
from survey group by month(period)