Jag har skapat en SQL-fiol av denna lösning för dig att leka med.
I huvudsak skapar den en arbetstabell @Månader och sedan går Cross samman med detta testamente alla år i din datamängd. Detta ger en komplett lista över alla månader för alla år. Jag lämnade sedan och sammanfogade testdata som tillhandahålls i ditt exempel (tabell med namnet TEST - se SQL-fiol för schema) tillbaka till den här listan för att ge mig en komplett lista med värden för månaderna som har dem. Nästa problem att lösa var att använda de senaste månadernas värden om denna månad inte hade några. För det använde jag en korrelerad underfråga, det vill säga slog tblValues tillbaka på sig själv endast där den matchade den maximala rankningen för en rad som har ett värde. Detta ger sedan en komplett resultatuppsättning!
Om du vill filtrera efter år\månad kan du lägga till detta i en WHERE-klausul precis innan den slutliga Order By.
Njut!
Testschema
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)
Fråga
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