Това е забързано като всичко, но трябва да ви осигури това, от което се нуждаете:
SELECT SUM(PERIOD_DIFF(EXTRACT(YEAR_MONTH FROM a.end_date), EXTRACT(YEAR_MONTH FROM a.start_date))) months
FROM (
SELECT MIN(g.start_date) start_date, MAX(g.end_date) end_date
FROM (
SELECT @group_id := @group_id + (@end_date IS NULL OR o.start_date > @end_date) group_id,
start_date,
@end_date := DATE(CASE
WHEN (@end_date IS NULL OR o.start_date > @end_date) THEN o.end_date
ELSE GREATEST(o.end_date, @end_date)
END) end_date
FROM overlap o
JOIN (SELECT @group_id := 0, @end_date := NULL) init
ORDER BY o.start_date ASC
) g
GROUP BY g.group_id
) a
Най-вътрешната заявка обединява вашите периоди в припокриващи се групи, като разтяга крайната дата, където е подходящо. End_date се огъва, тъй като предположих, че може да има периоди, изцяло обградени от предишната.
Следващата заявка за обвиване извлича пълния диапазон от всяка група.
Външната заявка обобщава пълните месечни разлики за всяка група. Всички групови разлики се закръгляват надолу до най-близкия пълен месец от PERIOD_DIFF.
За съжаление не можах да тествам това, тъй като SQLFiddle умря върху мен.