Create a lookup table with a cartesian join, then use that in a left join, and do a case when for missing values:
data data1;
input year;
cards;
2012
2013
2014
;
run;
data data2;
input state $ year value;
cards;
A 2012 4
A 2013 6
B 2013 10
;
run;
proc sql;
create table all_states as
select distinct
a.year,
b.state
from
data1 a,
data2 b
;
create table want as
select
a.year,
a.state,
case
when b.value is missing then 0
else b.value
end as value
from
all_states a left join data2 b
on a.year = b.year and a.state = b.state
order by
a.state,
a.year
;
quit;
proc print data=want noobs;
run;
Result:
year state value
2012 A 4
2013 A 6
2014 A 0
2012 B 0
2013 B 10
2014 B 0
Note how I present example data in data steps with datalines, for easy use by others (just a copy/paste and submit is needed to reliably recreate the dataset). See it as a basic courtesy for potential helpers.