Your first outer join , as expected, creates:
| REASON | MONTH |
-------------------
| A | May |
| A | May |
| A | July |
| A | June |
| B | May |
| B | June |
| D | (null) |
However, since external joins produce results if the join condition is satisfied at least once (and enters only NULL entries if the condition is never fulfilled), your second outer join does not record for (B, July) ; it also falls completely Reason = 'D' because the join condition is not fulfilled (and all three months have been met elsewhere):
| REASON | MONTH |
------------------
| A | May |
| A | May |
| B | May |
| A | June |
| B | June |
| A | July |
As long as you can eliminate the loss of Reason = 'D' adding OR a.Month IS NULL to your join condition, you still won't create (B, July) , Instead, since you want to get every pair (Reason, Month) , you CROSS JOIN must materialize the Reasons table in their materialized Months table:
SELECT Reason, Month FROM ( SELECT 'A' AS Reason UNION ALL SELECT 'B' UNION ALL SELECT 'D' ) Reasons CROSS JOIN ( SELECT 'May' AS Month UNION ALL SELECT 'June' UNION ALL SELECT 'July' ) Months
| REASON | MONTH |
------------------
| A | May |
| B | May |
| D | May |
| A | June |
| B | June |
| D | June |
| A | July |
| B | July |
| D | July |
Take a look at sqlfiddle .
Then you just need the external connection of the result to your underlying data:
SELECT Reason, Month, SUM(Down_time) downtime FROM ( SELECT 'A' AS Reason UNION ALL SELECT 'B' UNION ALL SELECT 'D' ) Reasons CROSS JOIN ( SELECT 'May' AS Month UNION ALL SELECT 'June' UNION ALL SELECT 'July' ) Months LEFT JOIN tabledown USING (Reason, Month) GROUP BY Reason, Month
| REASON | MONTH | DOWNTIME |
-----------------------------
| A | July | 3 |
| A | June | 8 |
| A | May | 7 |
| B | July | (null) |
| B | June | 6 |
| B | May | 5 |
| D | July | (null) |
| D | June | (null) |
| D | May | (null) |
Take a look at sqlfiddle .