WITH a AS
(SELECT nd, md, months_between(md, nd) diff
FROM (SELECTMIN(dates) nd, MAX(dates) md FROM test))
SELECT a1.dates,
nvl(s.key, lag(key ignore NULLS) over(ORDERBY a1.dates)) AS newkey
FROM (SELECT add_months(nd, (LEVEL - 1)) AS dates
FROM a
CONNECTBYLEVEL <= diff + 1) a1
LEFTJOIN test s
ON a1.dates = s.dates
ORDERBY1;