I have sales data by years and quarters and for the last year I want to fill missing quarters with last available value.
Say we have source table:
+------+---------+-------+--------+ | year | quarter | sales | row_no | +------+---------+-------+--------+ | 2018 | 1 | 4000 | 5 | | 2018 | 2 | 6000 | 4 | | 2018 | 3 | 5000 | 3 | | 2018 | 4 | 3000 | 2 | | 2019 | 1 | 8000 | 1 | +------+---------+-------+--------+
Desired results:
+------+---------+-------+------------------------+ | year | quarter | sales | | +------+---------+-------+------------------------+ | 2018 | 1 | 4000 | | | 2018 | 2 | 6000 | | | 2018 | 3 | 5000 | | | 2018 | 4 | 3000 | | | 2019 | 1 | 8000 | | | 2019 | 2 | 8000 | <repeat the last value | | 2019 | 3 | 8000 | <repeat the last value | | 2019 | 4 | 8000 | <repeat the last value | +------+---------+-------+------------------------+
So the task is to make Cartesian of year and quarter and left join to it the sales either corresponding or the last.
This code gets me almost there:
select r.year, k.quarter, t.sales from (select distinct year from [MyTable]) r cross join (select distinct quarter from [MyTable]) k left join [MyTable] t on (r.year = t.year and k.quarter=t.quarter) or row_no=1
How to correct the last line (condition of join) so thet the 2018 is not doubled?
Advertisement
Answer
One method uses outer apply:
select y.year, q.quarter, t.sales from (select distinct year from [MyTable]) y cross join (select distinct quarter from [MyTable]) q outer apply (select top (1) t.* from [MyTable] t where t.year < y.year or (t.year = y.year and t.quarter <= q.quarter) order by t.year desc, t.quarter desc ) t;
For your volume of data, this should be fine.
A more efficient method — assuming you are only assigning values to the end — would be:
select y.year, q.quarter, coalesce(t.sales, tdefault.sales) from (select distinct year from [MyTable]) y cross join (select distinct quarter from [MyTable]) q left join [MyTable] t on t.year = y.year and t.quarter = q.quarter cross join (select top (1) t.* from [MyTable] t order by t.year desc, t.quarter desc ) tdefault