Solved by doing a union first, to get the data per the suggested answer (single column format). The suggested answer doesn't consolidate similar data from multiple columns. Then you can work with the temporary results and transform as required. Further, it has to be a stored procedure, to the statement won't execute with results.
DELIMITER $$
DROP PROCEDURE IF EXISTS `civicrm_report_tmp_volunteer`$$
CREATE PROCEDURE `civicrm_report_tmp_volunteer`()
BEGIN
DROP TABLE IF EXISTS civicrm_report_tmp_volunteer_hours;
SET @group_concat_max_len = 5000;
CREATE TEMPORARY TABLE civicrm_report_tmp_volunteer_hours AS
SELECT
CONCAT(c.first_name, ' ' , c.last_name) as contact_name,
a.contact_id as contact_id,
EXTRACT( YEAR_MONTH FROM ca.activity_date_time ) as sort_date,
CONCAT(
MONTHNAME(STR_TO_DATE(EXTRACT( MONTH FROM ca.activity_date_time), '%m')),
"-",
EXTRACT( YEAR FROM ca.activity_date_time )) as month_year,
-- a.activity_id,
-- ca.activity_type_id,
-- ca.activity_date_time,
-- ca.duration,
SUM(ca.duration) as activity_duration,
COUNT(DISTINCT (a.activity_id)) activity_count
FROM
(
SELECT volunteer_1_543 as contact_id, entity_id as activity_id FROM civicrm_value_volunteer_details_103
WHERE volunteer_1_543 IS NOT NULL
UNION
SELECT volunteer_2_544 as contact_id, entity_id as activity_id FROM civicrm_value_volunteer_details_103
WHERE volunteer_2_544 IS NOT NULL
UNION
SELECT volunteer_3_545 as contact_id, entity_id as activity_id FROM civicrm_value_volunteer_details_103
WHERE volunteer_3_545 IS NOT NULL
UNION
SELECT volunteer_4_546 as contact_id, entity_id as activity_id FROM civicrm_value_volunteer_details_103
WHERE volunteer_4_546 IS NOT NULL
) as a
LEFT JOIN civicrm_activity ca
ON a.activity_id = ca.id
LEFT JOIN civicrm_contact c
ON c.id = a.contact_id
WHERE ca.activity_type_id IN (184)
GROUP BY a.contact_id, month_year;
SET @query = null;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(sort_date = ''',
sort_date,
''', activity_duration, 0)) AS ',
"'", month_year, "' "
)
) INTO @query
FROM civicrm_report_tmp_volunteer_hours;
SET @query = CONCAT('SELECT contact_name, ', @query , ' FROM civicrm_report_tmp_volunteer_hours GROUP BY contact_id');
PREPARE stmt FROM @query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
CALL civicrm_report_tmp_volunteer();