Създадох SQL Fiddle на това решение, с което да играете.
По същество той създава работна таблица @Months и след това Cross се присъединява към това всички години във вашия набор от данни. Това създава пълен списък на всички месеци за всички години. След това напуснах присъединяването на тестовите данни, предоставени във вашия пример (Таблица с име TEST - вижте SQL fiddle за схема) обратно в този списък, за да ми даде пълен списък със стойности за месеците, в които ги има. Следващият проблем за преодоляване беше използването на стойности от последните месеци, ако тези месеци нямаше такива. За това използвах корелирана подзаявка, т.е. присъединих tblValues обратно към себе си само когато съответства на максималния ранг на ред, който има стойност. След това това дава пълен набор от резултати!
Ако искате да филтрирате по година\месец, можете да добавите това в клауза WHERE точно преди окончателния ред по.
Насладете се!
Тестова схема
CREATE TABLE TEST( Month tinyint, Year int, Value int)
INSERT INTO TEST(Month, Year, Value)
VALUES
(1,2013,100),
(4,2013,101),
(8,2013,102),
(2,2014,103),
(4,2014,104)
Заявка
DECLARE @Months Table(Month tinyint)
Insert into @Months(Month)Values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12);
With tblValues as (
select Rank() Over (ORDER BY y.Year, m.Month) as [Rank],
m.Month,
y.Year,
t.Value
from @Months m
CROSS JOIN ( Select Distinct Year from Test ) y
LEFT JOIN Test t on t.Month = m.Month and t.Year = y.Year
)
Select t.Month, t.Year, COALESCE(t.Value, t1.Value) as Value
from tblValues t
left join tblValues t1 on t1.Rank = (
Select Max(tmax.Rank)
From tblValues tmax
Where tmax.Rank < t.Rank AND tmax.Value is not null)
Order by t.Year, t.Month