简体   繁体   中英

Nested loop in SAS macro

I got error when I was trying to use macro nested loop in SAS:

%Let t1=30;
%Let t2=40;
%Let t3=50;
%Let t4=60;
%Let t5=70;

%macro Age(time);
%Do I = 1 %to &time.; 
data Milk&I;
set Milk;
/*If Age is less than 30, MilkF and MilkA after 30 should be 0, same for 40-70*/

where (age<&&t&I. and (%Do I = &I. %to 5;
                              MilkF&&t&I. ne 0 or MilkA&&t&I. ne 0 ; 
                        %end;) ) ;

run;
%end;
%mend Age;
%Age(5)

The error shows behind the last "ne 0;" Syntax Error. What's the problem? Thanks for your help!

UPDATE: The output from macro I want is (takeing t1=30 as an example):

where (age<30 and (
               MilkF30 ne 0 or MilkA30 ne 0 or 
               MilkF40 ne 0 or MilkA40 ne 0 or
               MilkF50 ne 0 or MilkA50 ne 0 or
               MilkF60 ne 0 or MilkA60 ne 0 or
               MilkF70 ne 0 or MilkA70 ne 0 
               ) ) ;

So I have changed my code to

where (age<&&t&I. and 
(%Do I = &I. %to 5;
 MilkFreq&&t&I. ne 0 or MilkAmnt&&t&I. ne 0 or
%end;
 ) ) ;

Error:

   ) ) ;  run;
  -
  22
  76

"ERROR: Syntax error while parsing WHERE clause." So what happened now?

I see a few different things wrong. Consider:

where (age<&&t&I. and (%Do I = &I. %to 5;
                              MilkF&&t&I. ne 0 or MilkA&&t&I. ne 0 ; 
                        %end;) ) ;

This would generate:

where (age<30 and (
                   MilkF30 ne 0 or MilkA30 ne 0 ;
                   MilkF40 ne 0 or MilkA40 ne 0 ;
                   MilkF50 ne 0 or MilkA50 ne 0 ;
                   MilkF60 ne 0 or MilkA60 ne 0 ;
                   MilkF70 ne 0 or MilkA70 ne 0 ;
                   ) ) ;
  1. If you look at the generated WHERE statement, it's invalid due to the extra semicolons. This causes the error message. To fix it, remove the semicolon in your macro at the end of MilkA&&t&I. ne 0 ; MilkA&&t&I. ne 0 ;

  2. The logic of those OR clauses doesn't look to me like what you describe in the comment, so you might want to check.

  3. As @Reeza points out, you are using the counter &i inside a loop that is using a counter &i. This typically won't cause a syntax error, but will cause either the outer loop to exit prematurely, or continue infinite looping. So you could use &j as the iterator for the inner loop. Also a good idea to declare &i and &j as %LOCAL to the macro, to avoid collisions with any similarly named macro variables in outer scopes.

UPDATE: Suggest you turn on OPTIONS MPRINT, and look at the code generated by the macro. With your edit:

where (age<&&t&I. and 
        (%do I = &I. %to 5;
           MilkFreq&&t&I. ne 0 or MilkAmnt&&t&I. ne 0 or
         %end;
         ) ) ;

you now have one too many ORs, because it will generate an extra OR at the end, ie MilkFreq70 ne 0 or MilkAmnt70 ne 0 or ) )

You could try something like:

where (age < &&t&i and 
        (%do j = &i %to 5;
           MilkFreq&&t&j ne 0 or MilkAmnt&&t&j ne 0 
           %if &j ne 5 %then or;
         %end;
         ) ) ;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM