Это ответ (будь то предположение, основанное на ограниченном вопросе). Я не фанат размещения операторов CASE внутри агрегатов, но в зависимости от среды, индексации и данных во включенных таблицах, это может работать нормально. Пожалуйста, будьте активнее при размещении сообщений. Покажите нам, что вы пробовали, объясните проблему, предоставьте образцы данных, включите желаемый результат, все эти забавные вещи. Чем лучше вопрос, тем больше шансов на хороший ответ. Хорошо, сделано на высоком коне ...
DECLARE @Forecast30days DATE
SET @Forecast30days = CURRENT_TIMESTAMP + 30
SELECT
wo.LOCATION
,COUNT(CASE WHEN wo.actfinish <= wo.targcompdate THEN wo.WONUM ELSE NULL END) AS OnTimePMWOs
,COUNT(CASE WHEN wo.actfinish >= wo.targcompdate THEN wo.WONUM ELSE NULL END) AS PastDuePMWOs
,COUNT(CASE WHEN pm.changedate IS NOT NULL THEN wo.WONUM ELSE NULL END) AS Forecast30days
FROM WORKORDER AS wo
LEFT JOIN PMFORECAST AS pm
ON wo.changedate = pm.changedate
AND pm.forecastdate >= @Forecast30days
WHERE wo.worktype = 'pm'
AND ((wo.actfinish IS NOT NULL AND wo.targcompdate IS NOT NULL)
OR (pm.changedate IS NOT NULL))
GROUP BY
wo.LOCATION