romina - Monday, June 25, 2018 8:28 AM
A solution using analytical function max() over(order by). This looks at all the available dates for an institution and generates 12 rows one for each month. I have slightly modified the input DML statements to test various scenarios. More complicated than the earlier solutions i guess but made more generic
CREATE TABLE data
(
ReportingMonth datetime,
Institution varchar(4),
Totals integer
);
GO
INSERT INTO data
VALUES
('2018-01-01','Ins1',32),
('2018-02-01','Ins1',37),
('2018-03-01','Ins1',32),
('2018-04-01','Ins1',40),
('2018-05-01','Ins1',38),
('2018-06-01','Ins1',37),
('2018-09-01','Ins1',40),
('2019-09-01','Ins1',42),
('2018-01-01','Ins2',145),
('2018-02-01','Ins2',155),
('2018-01-01','Ins3',1489),
('2018-02-01','Ins3',1487),
('2018-03-01','Ins3',1485);
GO
with generate_12_months
as (
select dateadd(month
,y.rnk-1
,cast(concat(year_val,'-','01','-','01') as date)
) as running_months
,x.institution
from (select top 12
row_number() over(order by (select null)) as rnk
from sys.objects
)y
join (select distinct /* for each distinct year in a institution generates 12 months*/
datepart(year,reportingmonth) as year_val
,Institution
from data
)x
on 1=1
)
,interim_data
as (
select cd.running_months
,cd.institution
,d.totals
,d.reportingmonth
from generate_12_months cd
left join data d
on cd.running_months=d.reportingmonth
and cd.institution=d.institution
)
,interim_data2
as(/*the max reportingmonth gets the first not null value of the month ordered by running_months*/
select *
,max(x.reportingmonth) over(partition by x.institution order by x.running_months) as max_val
from interim_data x
)
select *
,max(y.totals) over(partition by y.institution,y.max_val) as not_null_totals
from interim_data2 y