sasmacrossas-macrodo-loopsmacro-variable

SAS Macro Variables


I am trying to create a macro that needs to reference 2 dates, I want this to be part of a do loop so I don't have to enter dates in 36 times.

Here's what I have so far:

PROC SQL NOPRINT;
SELECT MMMYY INTO : mmmyy1 -
FROM USE_DATES;
%LET T=&SQLOBS.;
QUIT;

PROC SQL NOPRINT;
SELECT _YEAR_ INTO : yy1 -
FROM USE_DATES;
%LET T=&SQLOBS.;
QUIT;

PROC SQL NOPRINT;
SELECT mm INTO : mm1 -
FROM USE_DATES;
%LET T=&SQLOBS.;
QUIT;


%MACRO MATS(DATE, NUM);
%let j=%eval(&i+1);
%let month = &mm&&j.;
%let year_x = &yy&&j.;

PROC SQL;
CREATE TABLE TEST AS 
SELECT 
PRODUCT_EXPIRY_DATE, 
COUNT(*)
FROM DATA.AGGREGATE_ACCOUNTS_&mmmyy&&i.
WHERE YEAR(PRODUCT_EXPIRY_DATE) = &year_x. AND MONTH(PRODUCT_EXPIRY_DATE) = &month.

;
QUIT;
%MEND;

%MACRO apply_MATS;
%DO i = 1 %to 1  %by 1;
%MATS(&mmmyy&&i.,&i.);
%end;
%mend;

%apply_MATS;

The problem is that it doesn't assign year_x so the code fails with the error code:

ERROR 22-322: Syntax error, expecting one of the following: a name, ;, (, ',', ANSIMISS, AS, CROSS, EXCEPT, FULL, GROUP, HAVING, INNER, INTERSECT, JOIN, LEFT, NATURAL, NOMISS, ORDER, OUTER, RIGHT, UNION, WHERE.

ERROR 200-322: The symbol is not recognized and will be ignored.

I can't work out what I've done wrong? Is anyone able to help?


Solution

  • You are not using the && in the right place. If &J=1 and want the value of YY1 then you should do:

    %let year_x = &&yy&j;
    

    The first pass will convert && into & and &J into 1 resulting in &yy1. Which the second pass will convert to the value of YY1.

    But you are making it much too hard. If the goal is to select by YEAR and MONTH then construct the inner macro in that way.

    %MACRO MATS(year, month, NUM);
    PROC SQL;
    CREATE TABLE TEST&num. AS 
      SELECT PRODUCT_EXPIRY_DATE
           , COUNT(*)
      FROM DATA.AGGREGATE_ACCOUNTS_&year.&month.
      WHERE YEAR(PRODUCT_EXPIRY_DATE) = &year
        AND MONTH(PRODUCT_EXPIRY_DATE) = &month.
    ;
    QUIT;
    %MEND;
    

    Then you can call the macro once for each combination of MM and YY.

    data _null_;
       set USE_DATES;
       call execute(cats('%nrstr(%MATS)(',yy,',',mm,',',_n_,')'));
    run;