Vytvořil jsem SQL Fiddle tohoto řešení, se kterým si můžete hrát.
V podstatě to vytvoří pracovní tabulku @Months a poté Cross připojí všechny roky ve vaší datové sadě. To vytváří úplný seznam všech měsíců pro všechny roky. Poté jsem nechal připojit data testu uvedená ve vašem příkladu (tabulka s názvem TEST – schéma viz SQL housle) zpět do tohoto seznamu, abych dostal úplný seznam s hodnotami pro měsíce, které je mají. Dalším problémem, který bylo třeba překonat, bylo použití hodnot z posledních měsíců, pokud tyto měsíce žádné neměly. K tomu jsem použil korelovaný dílčí dotaz, tj. spojené tblValues zpět na sebe pouze tam, kde odpovídalo maximální hodnosti řádku, který má hodnotu. Tím získáte kompletní sadu výsledků!
Pokud chcete filtrovat podle roku/měsíce, můžete to přidat do klauzule WHERE těsně před konečnou objednávku podle.
Užijte si to!
Testovací schéma
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)
Dotaz
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