You are creating additional, likely unneeded complexity by including the underscore since that forces this to be a CHARACTER variable. With that construction your SNO will not sort properly if there are more than 9 rows for each Id value. 1_10 will sort before 1_2 in general. So not a nice serial number.
data want;
set have;
by id;
retain counter;
if first.id then counter=1;
else counter+1;
length sno $ 15;
sno = catx('_',id,counter);
drop counter;
run;