假设某个范围内的月数不超过 100:
SELECT id,
datefrom,
datetill,
amount,
monthstart,
monthfinish,
amount * (DATEDIFF(LEAST(datetill, monthfinish), GREATEST(datefrom, monthstart)) + 1) / (DATEDIFF(datetill, datefrom) + 1) monthamount
FROM ( SELECT test.*,
(test.datefrom - INTERVAL DAY(test.datefrom) - 1 DAY) + INTERVAL numbers.num MONTH monthstart,
LAST_DAY((test.datefrom - INTERVAL DAY(test.datefrom) - 1 DAY) + INTERVAL numbers.num MONTH) monthfinish
FROM test
JOIN ( SELECT t1.num*10+t2.num num
FROM (SELECT 0 num UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1
JOIN (SELECT 0 num UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2
) numbers
HAVING monthstart <= test.datetill
AND monthfinish >= test.datefrom
) subquery
ORDER BY id, monthstart;
小提琴
PS。如果总和在最后一位不匹配,请不要感到惊讶。