Edit, I noted in your test data you had 2107 year values, I assume these were typed incorrectly and fixed them.
If the new data is true, then all you have to do is a minor update to table A before the merge:
data A;
input caldt $ TNA $;
cards;
20170325 20
20170326 .
20170327 .
20170328 50
20170329 120
20170330 50
20170331 87
run;
data B;
input caldt $ mret $;
cards;
20170325 .
20170326 .
20170327 0.45
20170328 0.98
20170329 0.67
20170330 0.50
20170331 0.87
run;
data a;
set a;
retain lstv;
if tna ne "" then lstv=tna;
if tna="" then tna=lstv;
run;
proc sql;
create table C as
select B.*,
A.TNA
from A
right join B
on A.CALDT=B.CALDT;
quit;
However, I assume here that the dates are really character, and that the first obs get copied down. What your probably after, which is slightly different, is to take a baseline value and use that for missing elements. In which case in your baseline data, create a flag (or logic) and pull that in and do a case when, for example if the first date was to be used for missings\;
proc sql;
create table C as
select B.*,
case when A.TNA is null then X.TNA else A.TNA end as TNA
from A
right join B
on A.CALDT=B.CALDT
left join (select TNA from A having input(CALDT,yymmdd10.)=min(input(CALDT,yymmdd10.))) X
on 1=1;
quit;
... View more