在从一个 table 拉出的循环中调用 execute 以执行宏

call execute inside a loop pulling from one table to execute a macro

我目前有波纹管

%macro sqlloop (event_id);

...lots of code, mostly proc sql segments ...

%mend;

生成输出 table(名为 export_table2)。我需要能够 运行 对另一个 table(名为 vars)中的每个值执行此代码数十次。我测试我想要它做什么的试用代码如下(基本上手动输入这 68 行的前两个值 table)

data ;

%let empl_nbr_var = '222';
%let fleet = '7ER';
%let position = 'A'; 
%let base = 'BWI';

%sqlloop(event_id = 1);
run;

data summary_pilots;
set work.export_table2;
run;

data;
%let empl_nbr_var = '111';
%let fleet = '320'; 
%let position = 'B'; 
%let base = 'CHS';

%sqlloop(event_id = 2);

run;

data summary_pilots;
set summary_pilots work.export_table2;
run;

这会产生每次执行的最终输出,堆叠成一个 table,称为 summary_pilots。我如何在循环中执行此操作,可能使用 call execute 遍历 vars 的每一行? vars 的列正是我需要的宏变量,我想遍历每一行以再次分配这些宏变量和 运行 我的 %sqlloop。感谢您的帮助!

编辑:

目前正在弄清楚 call execute 是如何工作的,看看它在这里有什么帮助,但仍然有点卡住...下面的代码完全按照您的想法工作,将 table 变量中的所有变量打印到日志中.

data ;
set work.vars;
call execute( '%put='|| strip(empl_nbr_var)  || ';
%put = ' || strip(fleet) ||';
%put = '|| strip(position) ||'; 
%put = ' || strip(base) ||';' );
run;

我正在尝试使用下面的代码,但由于奇怪地分配了宏,我遇到了很多错误。 vars 列中的类型与我希望它们在宏中的类型完全匹配,但它看起来仍然可能是这里的问题?

data ;
set work.vars;
call execute( '
%let empl_nbr_var =' || strip(empl_nbr_var)  || ';
%let fleet = ' || strip(fleet) ||';
%let position = '|| strip(position) ||'; 
%let base = ' || strip(base) ||';

%sqlloop(event_id = 17);' );
run;

事件 ID 在这里实际上并不重要,所以我暂时将其保留为随机数。

假设您的 work.Vars 包含这样的数据:

empl_nbr_var fleet position base
222 7ER A BWI
111 320 B CHS
... ... ... ...

考虑扩展您的宏以接收此类输入参数:

%macro sqlloop(event_id, empl_nbr_var, fleet, position, base);

    ...lots of code, mostly proc sql segments ...

%mend;

然后,通过 call execute 使用连接的数据值构建 运行 宏。下面将 17 传递给 event_id 参数。

data _null_;
    set Work.Vars;

    args = catx("', '", empl_nbr_var, fleet, position, base);
    args = '%sqlloop(17,'''|| strip(args) || ''');';
    put args $char.;      /* VIEW CALL COMMAND */

    call execute(args);   /* RUN CALL COMMAND */
run;

在数据步骤中间编写 %LET 语句毫无意义。宏处理器将在将数据步骤代码的文本传递给 SAS 进行处理之前对其进行评估。通过在数据步骤之前移动 %LET 语句来避免混淆自己。

如果宏需要宏变量的值,如 FLEET,作为输入,那么将这些东西作为宏的参数。不要创建引用“魔术”宏变量的宏,即既不是输入参数也不是由宏创建的宏变量。相反,对它们的引用只是出现在宏定义的中间,就好像它们的值会以某种方式神奇地出现一样。

%macro sqlloop(empl_nbr_var,fleet,position,base);
  ... code that uses &fleet. 
  
%mend;

如果您希望通过宏 运行 有很多参数组合,请先将它们收集到数据集中。

data inputs ;
  input empl_nbr_var fleet $ position $ base $ ;
cards;
222 7ER A BWI
111 320 B CHS
;

然后您可以使用这些数据集变量来生成对宏的调用。您可以尝试使用 call execute() 来执行此操作,但我个人发现使用数据步骤将代码写入文件要容易得多。然后您可以检查文件并确保代码生成逻辑正确。另外,您可以使用 PUT 语句的强大功能来简化代码生成。例如,如果变量名称与参数名称匹配,您可以使用命名输出。

filename code temp;
data _null_;
  set inputs;
  file code ;
  put '%sqlloop(' empl_nbr_var= ',' fleet= ',' position= ',' base= ')';
run;

这将生成如下代码:

%sqlloop(empl_nbr_var=222 ,fleet=7ER ,position=A ,base=BWI )
%sqlloop(empl_nbr_var=111 ,fleet=320 ,position=B ,base=CHS )

一旦您确信它正在生成正确的代码,请使用 %INCLUDE 命令 运行 它生成的代码。

%include code / source2;

如果宏没有自己的聚合结果步骤,您可以在代码生成中包含该步骤。

filename code temp;
data _null_;
  set inputs;
  file code ;
  put '%sqlloop(' empl_nbr_var= ',' fleet= ',' position= ',' base= ')';
  put 'proc append base=summary_pilots data=export_table force; run;' ;
run;
%include code / source2;