我有一个宏,它将生成一个包含列prod和另外12列的数据集。我还有一个表prodincl_fr,其中包含下面的示例数据集。
Rownum prodcat
----------
1 L
2 L1
3 M
4 LM
... ...
我想做一个do until循环,它将调用宏%runlimitsquery并在每次迭代中使用prodcat的值。
我无法弄清楚如何在SAS中编写这个代码。我正在玩下面的代码。注意reccount = prodincl_fr的行数。
data _null_;
set prodincl_fr;
do until(rownum=reccount);
prod=prodcat;
call execute('%nrstr(%runlimitsquery(&prod))');
output;
end;
run;
希望你能帮助我。请!
答案 0 :(得分:1)
如果已知的codegen数量少于64K字符,则可以使用SQL来准备宏调用。我觉得这种代码风格对读者来说特别清楚。
%macro runlimitsquery(prodcat);
%put &sysmacroname called with &=prodcat;
%mend;
data prodcats;
input prodcat $ @@;
datalines;
auto boat home flood aux worker life
run;
proc sql noprint;
select
cats('%runlimitsquery(',prodcat,')')
into
:invoker separated by ' '
from
prodcats
;
quit;
%put NOTE: invoker=%superq(invoker); * lets see what is going to be invoked (the codegen);
* invoke the codegen;
&invoker
日志的最后部分
134 %put NOTE: invoker=%superq(invoker); * lets see what is going to be invoked (the codegen);
NOTE: invoker=%runlimitsquery(auto) %runlimitsquery(boat) %runlimitsquery(home)
%runlimitsquery(flood) %runlimitsquery(aux) %runlimitsquery(worker) %runlimitsquery(life)
135
136 * invoke the codegen;
137 &invoker
RUNLIMITSQUERY called with PRODCAT=auto
RUNLIMITSQUERY called with PRODCAT=boat
RUNLIMITSQUERY called with PRODCAT=home
RUNLIMITSQUERY called with PRODCAT=flood
RUNLIMITSQUERY called with PRODCAT=aux
RUNLIMITSQUERY called with PRODCAT=worker
RUNLIMITSQUERY called with PRODCAT=life
如果codegen将超过64k字符,您可能想退后一步,重新考虑手头任务的内容和方式。
答案 1 :(得分:0)
您的代码存在一些问题。
reccount
不是prodincl_fr
数据集的变量,因此不存在于该datastep的上下文中。因此do
语句等同于do until(rownum=.)
until
条件永远不会得到满足,您的代码将永远运行。&prod
是对宏变量的引用。但是当您在prod=prodcat
步骤中编写data
时,您将创建一个数据步变量,而不是宏变量。因此&prod
不存在。prod
宏变量存在,也无法解析,因为对它的引用用单引号括起来。 SAS不会尝试在单引号字符串中解析宏代码/引用。你需要使用双引号。该代码将语法正确,如下所示:
data _null_;
set prodincl_fr nobs=reccount;
do i=1 to reccount;
prod=prodcat;
call execute('%runlimitsquery('||prod||');');
output;
end;
run;
HOWEVER ,如果,让我们说prodincl_fr
包含一千条记录,那会怎么做:你的datastep会转到{{1}的第一条记录}},启动循环,该循环将使用prodincl_fr
的相同值调用您的宏一千次,这将是当前记录的prod
的值;然后它会移动到第二个记录并用该记录的prodcat值再调用一千次;等等,直到千分之一记录。
因为我认为这不是你想要的,并且因为带有prodcat
语句的数据步骤隐式迭代所有记录,你可以取消do循环并像这样编写你的datastep: / p>
set