Я пробовал много разных способов использования этой таблицы [monthTable], начиная с RIGHT JOIN и т. Д. Ни один из них не дал успешных результатов, фактически почти все, что я делаю, дает тот же набор результатов, что и выше.
FROM projects p WHERE p.status=3
Я предполагаю, что вы пытались что-то вроде этого
FROM projects p
RIGHT JOIN monthTable m on <join p to m>
WHERE p.status=3`
Проблема в том, что предложение WHERE будет отфильтровывать все записи, которые не имеют значений p.status (null). Вам нужно переместить такие фильтры в предложение JOIN, как это
FROM projects p
RIGHT JOIN monthTable m on <join p to m> AND p.status=3`
Любопытно, но как этого достаточно для таблицы, особенно с monthName, являющимся только varchar (3)?
monthID int Primary Key, monthName VARCHAR(3).
Попробуйте вместо этого создать его (один раз)
DROP PROCEDURE IF EXISTS FillMonthsTable;
delimiter //
CREATE PROCEDURE FillMonthsTable()
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
drop table if exists monthsTable;
create table monthsTable (theYear int, theMonth int, monthName varchar(20));
SET @x := date('2000-01-01');
REPEAT
insert into monthsTable (theyear, themonth, monthname) SELECT year(@x), month(@x), monthname(@x);
SET @x := date_add(@x, interval 1 month);
UNTIL @x > date('2030-01-01') END REPEAT;
END//
delimiter ;
CALL FillMonthsTable;
DROP PROCEDURE FillMonthsTable;
Затем, используя этот запрос (1 проход, чтобы сгруппировать ваши данные, затем левое соединение, чтобы получить 0)
SELECT m.theYear, m.theMonth, IFNULL(t.pNum, 0) theCount
FROM monthsTable m
LEFT JOIN (
SELECT YEAR(p.pEndDate) AS pYear, MONTH(p.pEndDate) AS pMonth, count(*) AS pNum
FROM projects p
WHERE p.status=3
GROUP BY YEAR(p.pEndDate), MONTH(p.pEndDate)
) t on t.pYear = m.theYear and t.pMonth = m.theMonth
ORDER BY m.theYear, m.theMonth