0

I have the following mysql query:

SELECT 
LEFT(MONTHNAME(date), 3) AS month,
YEAR(date) AS year,
COUNT(id) AS quantity
FROM
budgets
GROUP BY MONTH(date)

which returns me this:

|month|year|quantity|
---------------------
|  Jan|2018|      10|
|  Mar|2018|       2|
|  May|2018|       5|

I need to show months even if COUNT(id) not exist like this:

|month|year|quantity|
---------------------
|  Jan|2018|      10|
|  Feb|2018|       0|
|  Mar|2018|       2|
|  Apr|2018|       0|
|  May|2018|       5|

Anyone knows a way to do that?

UPDATE

According to D-Shih answer code, query returns this:

|month|year|quantity|
---------------------
|  Jan|2018|      10|
|  Feb|null|       0|
|  Mar|2018|       2|
|  Apr|null|       0|
|  May|2018|       5|

And if I add a register with different year it will show only one row with name 2017 like:

|month|year|quantity|
---------------------
|  Jan|2018|      10|
|  Feb|null|       0|
|  Mar|2018|       2|
|  Apr|null|       0|
|  May|2018|       5|
|  May|2017|       2|

it must show

|month|year|quantity|
---------------------
|  Jan|2018|      10|
|  Feb|2018|       0|
|  Mar|2018|       2|
|  Apr|2018|       0|
|  May|2018|       5|
|  Jan|2017|       0|
|  Feb|2017|       0|
|  Mar|2017|       0|
|  Apr|2017|       0|
|  May|2017|       2|

2 Answers2

0

If you want to scale this, I think this should work. Not very sure about how efficient it would be though:

SELECT a.month AS month, a.year AS year, COALESCE(b.quantity,0) AS quantity
FROM
(
   SELECT DISTINCT MONTH(date) AS month, YEAR(date) AS year
   FROM
   budgets
) a
LEFT JOIN
(
   SELECT MONTH(date) AS month, YEAR(date) AS year,
   COUNT(id) AS quantity
   FROM
   budgets
   GROUP BY MONTH(date), YEAR(date)
) b
ON a.month = b.month AND a.year = b.year
Vishnu Kunchur
  • 1,716
  • 8
  • 9
0

You can try to make a calendar table and OUTER JOIN base on the calendar table

SELECT t1.month,
       y.year AS year,
       COUNT(t2.id) 
FROM (
    SELECT 'Jan' month
    UNION ALL
    SELECT 'Feb' month
    UNION ALL
    SELECT 'Mar' month
    UNION ALL
    SELECT 'Apr' month
    UNION ALL
    SELECT 'May' month
) t1 
CROSS JOIN (SELECT DISTINCT YEAR(date) FROM budgets) y  
LEFT JOIN budgets t2 on t1.month = LEFT(MONTHNAME(t2.date), 3) 
   AND y.year = YEAR(t2.date)
GROUP BY t1.month, y.year

Here is a sample for you.

Schema (MySQL v8.0)

CREATE TABLE budgets (
   `month` varchar(5),
   `year` int,
   quantity int
);


insert into budgets values ('Jan',2018,10);
insert into budgets values ('Mar',2018,2);
insert into budgets values ('May',2018,5);
insert into budgets values ('May',2017,2);

Query #1

| month | year | quantity |
| ----- | ---- | -------- |
| Jan   | 2018 | 10       |
| Mar   | 2018 | 2        |
| May   | 2018 | 5        |
| May   | 2017 | 2        |
| Jan   | 2017 | 0        |
| Feb   | 2018 | 0        |
| Feb   | 2017 | 0        |
| Mar   | 2017 | 0        |
| Apr   | 2018 | 0        |
| Apr   | 2017 | 0        |

View on DB Fiddle

D-Shih
  • 44,943
  • 6
  • 31
  • 51