SQL DEMO
SELECT q.year
, q.month
, q.name
, COUNT(CASE WHEN q.last_status = 2 THEN 1 END) as pre_implementation
, COUNT(CASE WHEN q.last_status = 3
AND q.previous_status = 2 THEN 1 END) as implementation_operation
, COUNT(CASE WHEN q.last_status = 3
AND (q.previous_status = 1 or q.previous_status IS NULL)
THEN 1 END) as pre_operation
FROM (
SELECT *, (SELECT MAX(p.status_id)
FROM project_status p
WHERE p.time < CONCAT(t.year,'/', t.month,'/1')
AND p.project_id = t.project_id
) as previous_status
FROM (
SELECT YEAR(time) as year
, MONTH(time) as month
, c.name
, ps.project_id
, MAX(status_id) as last_status
FROM project_status ps
JOIN projects p
ON ps.project_id = p. project_id
JOIN investments i
ON p.investment_id = i.investment_id
JOIN categories c
ON i.cat_id = c.cat_id
GROUP BY YEAR(time), MONTH(time), c.name, ps.project_id
) t
) q
GROUP BY q.year, q.month, q.name
SAÍDA
+--------+-------+---------------+--------------------+--------------------------+---------------+
| year | month | name | pre_implementation | implementation_operation | pre_operation |
+--------+-------+---------------+--------------------+--------------------------+---------------+
| 2019 | 2 | Technology | 0 | 0 | 0 |
| 2019 | 3 | Technology | 1 | 0 | 0 |
| 2019 | 4 | services | 0 | 0 | 0 |
| 2019 | 5 | agriculture | 0 | 0 | 0 |
+--------+-------+---------------+--------------------+--------------------------+---------------+
| 2019 | 8 | Technology | 0 | 1 | 0 |
| 2019 | 8 | agriculture | 1 | 0 | 1 |
| 2019 | 8 | services | 0 | 0 | 1 |
| 2019 | 8 | manufactures | 1 | 0 | 0 |
+--------+-------+---------------+--------------------+--------------------------+---------------+