Flag the result values into 3 categories, Y-less than 40 , N - greater than 40 and M missing values and then later read all the values for the group and searching the combined string would answer your question.
data have;
input subject visit:$3. result tst:$3.;
datalines;
101 d1 20 EST
101 d2 30 EST
101 d3 40 EST
101 d4 50 EST
101 P1 40 EST
101 P2 50 EST
101 P3 60 EST
101 P4 70 EST
;
run;
proc format ;
value flag low-<40='Y'
.='M'
other='N';
run;
data want_grp;
set have;
visit_grp=substr(visit,1,1);
result_Flag=put(result,flag.);
run;
proc sort data=want_grp;
by subject visit_grp;
data want;
format result_Flag_cat $15.;
do until (last.visit_grp);
set want_grp;
by subject visit_grp;
result_Flag_cat=cats(result_Flag_cat,result_Flag); /* All values in last record */
end;
/* If Y exists then atleast one values has less than 40 */
if find(result_Flag_cat,'Y')>0 then c1='Y' ; else c1='N';
/* If no Y or M then all values are greater than 40 */
if find(result_Flag_cat,'Y')=0 and find(result_Flag_cat,'M')=0 then c2='Y' ; else c2='N';
/* If atleast one values is missing */
if find(result_Flag_cat,'M')>0 then mc1='Y'; else mc1='N';
/* If all results are missing, i.e. no Y or N */
if find(result_Flag_cat,'M')>0 and find(result_Flag_cat,'Y')=0 and find(result_Flag_cat,'N')=0 then mc2='Y' ; else mc2='N';
run;
... View more