SELECT CONCAT(DATE(dumper_cycles.t_stamp), ' ', HOUR(dumper_cycles.t_stamp), ':00') AS StartTimestamp, CONCAT('H', TIMESTAMPDIFF(HOUR, DATE_FORMAT(dumper_cycles.t_stamp, "%Y-%m-%d %H:00:00"), DATE_FORMAT(NOW(), "%Y-%m-%d %H:00:00"))) AS Hour, CONCAT(CAST(COALESCE(SUM(dumper_cycles.ulc1 = 1), 0) AS CHAR),' cph') AS ULC1, CONCAT(CAST(COALESCE(SUM(dumper_cycles.ulc2 = 1), 0) AS CHAR),' cph') AS ULC2, CONCAT(CAST(COALESCE(SUM(dumper_cycles.ulc3 = 1), 0) AS CHAR),' cph') AS ULC3, CONCAT(CAST(COALESCE(SUM(dumper_cycles.ulc4 = 1), 0) AS CHAR),' cph') AS ULC4 FROM dumper_cycles WHERE (dumper_cycles.t_stamp BETWEEN :starttime AND :endtime) GROUP BY HOUR(dumper_cycles.t_stamp) UNION ALL -- Default row with zeros when no dumper cycles exist SELECT CONCAT(DATE(:starttime), ' ', HOUR(:starttime), ':00') AS StartTimestamp, CONCAT('H', TIMESTAMPDIFF(HOUR, DATE_FORMAT(:starttime, "%Y-%m-%d %H:00:00"), DATE_FORMAT(NOW(), "%Y-%m-%d %H:00:00"))) AS Hour, '0 cph' AS ULC1, '0 cph' AS ULC2, '0 cph' AS ULC3, '0 cph' AS ULC4 WHERE NOT EXISTS ( SELECT 1 FROM dumper_cycles WHERE dumper_cycles.t_stamp BETWEEN :starttime AND :endtime );