Ho creato un SQL Fiddle di questa soluzione con cui giocare.
In sostanza, crea una tabella di lavoro al mese e quindi Cross si unisce a questo per tutti gli anni nel tuo set di dati. Questo produce un elenco completo di tutti i mesi per tutti gli anni. Ho quindi lasciato unire i dati di test forniti nel tuo esempio (Tabella denominata TEST - vedi SQL fiddle per lo schema) in questo elenco per darmi un elenco completo con i valori per i mesi che li hanno. Il problema successivo da superare è stato l'utilizzo dei valori degli ultimi mesi se questi mesi non ne avevano. Per questo, ho usato una sottoquery correlata, ad es. tblValues unito su se stesso solo dove corrispondeva al Rank massimo di una riga che ha un valore. Questo dà quindi un set di risultati completo!
Se desideri filtrare per anno\mese puoi aggiungerlo in una clausola WHERE appena prima dell'ordine finale entro.
Divertiti!
Schema di prova
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)
Interroga
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