在从一个 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;
我目前有波纹管
%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;