我正在尝试创建一个需要引用 2 个日期的宏,我希望它成为 do 循环的一部分,这样我就不必输入 36 次日期。
这是我到目前为止所拥有的:
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;
问题是它没有分配year_x,因此代码失败并显示错误代码:
错误 22-322:语法错误,需要以下之一:名称、;、(、'、'、ANSIMISS、AS、 交叉、除外、完整、分组、具有、内部、相交、连接、左、自然、 NOMISS、ORDER、OUTER、RIGHT、UNION、WHERE。
错误 200-322:该符号无法识别,将被忽略。
我无法弄清楚我做错了什么?有人可以帮忙吗?
您没有在正确的位置使用 &&。如果 &J=1 并且想要 YY1 的值,那么你应该这样做:
%let year_x = &&yy&j;
第一遍会将 && 转换为 &,并将 &J 转换为 1,得到 &yy1。第二遍将转换为 YY1 的值。
但你把事情搞得太难了。如果目标是按 YEAR 和 MONTH 选择,则以这种方式构造内部宏。
%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;
然后你可以为YYMM的每个值调用一次宏
data _null_;
set USE_DATES;
call execute(cats('%nrstr(%MATS)(',yy,',',mm,',',_n_,')'));
run;