Macros SAS宏传递要在宏中使用的SQL或代码
我对SAS宏编程比较陌生,我主要使用它使我的代码“更干净”,避免重复代码中的错误 我做了一些谷歌搜索,但并没有找到简单的方法 首先我有两个问题-如何将列列表传递给宏 我想让宏在一般代码中看起来像这样:Macros SAS宏传递要在宏中使用的SQL或代码,macros,sas,sas-macro,proc-sql,Macros,Sas,Sas Macro,Proc Sql,我对SAS宏编程比较陌生,我主要使用它使我的代码“更干净”,避免重复代码中的错误 我做了一些谷歌搜索,但并没有找到简单的方法 首先我有两个问题-如何将列列表传递给宏 我想让宏在一般代码中看起来像这样: proc sql; create table &usefulTable as %DoStuff('col1, col3, col9', 'col1 = 12 or (col2 between 1 and 3)') ; 基本上,我将列值作为第一个参数传递,将where子句作为第二个参数传
proc sql;
create table &usefulTable as
%DoStuff('col1, col3, col9', 'col1 = 12 or (col2 between 1 and 3)')
;
基本上,我将列值作为第一个参数传递,将where子句作为第二个参数传递
是否可以使宏what作为列名通过第一个参数,并使用第二个参数作为where子句的一部分
%MACRO DoStuff(col, cond);
select
&col separated by ',' ,
'source1' as source
from &someNiceTable
where &cond
union
select
&col separated by ',' ,
'source2' as source
from &someNiceOtherTable
where &cond
%mend;
上面是一个示例基本宏,显示了我打算执行的类似功能,在本例中是两个表的并集,同时添加了新列,定义了从哪个表设置为记录。基本上,对几个表总是应用相同的条件,然后它们将通过union连接,并添加一个额外的列
能在这件事上找些杰普就好了
老实说,我面临的最大问题是传递WARE变量,因为我可以在宏中使用列名作为硬编码值,但问题是where子句,因为它会定期更改。您的思路是正确的。您引用这些参数部分是正确的,因为第一个参数(列列表)将被解释为3个单独的参数,而另一个参数(其中条件)将被解释为名为
col1
的关键字参数。但是,这将要求您在宏定义中引用这些参数。更简单的方法是在宏调用中使用%str()
您在proc sql
中使用了以分隔的,这也是不正确的。这与into
语句一起使用,将select
语句中的值存储到宏变量中
您的宏应该如下所示:
%MACRO DoStuff(col, cond);
select
&col,
'source1' as source
from &someNiceTable
where &cond
union
select
&col,
'source2' as source
from &someNiceOtherTable
where &cond
%mend;
电话应该是这样的:
proc sql;
create table &usefulTable as
%DoStuff(%str(col1, col3, col9), %str(col1 = 12 or (col2 between 1 and 3)))
;
quit;
你在正确的轨道上。您引用这些参数部分是正确的,因为第一个参数(列列表)将被解释为3个单独的参数,而另一个参数(其中条件)将被解释为名为col1
的关键字参数。但是,这将要求您在宏定义中引用这些参数。更简单的方法是在宏调用中使用%str()
您在proc sql
中使用了以
分隔的,这也是不正确的。这与into
语句一起使用,将select
语句中的值存储到宏变量中
您的宏应该如下所示:
%MACRO DoStuff(col, cond);
select
&col,
'source1' as source
from &someNiceTable
where &cond
union
select
&col,
'source2' as source
from &someNiceOtherTable
where &cond
%mend;
电话应该是这样的:
proc sql;
create table &usefulTable as
%DoStuff(%str(col1, col3, col9), %str(col1 = 12 or (col2 between 1 and 3)))
;
quit;
如果您将值作为带引号的字符串传递,并且希望在不带引号的情况下使用它们,则可以使用%SYSFUNC()
宏函数调用DEQUOTE()
函数
%MACRO DoStuff(col, cond);
select %sysfunc(dequote(&col))
, 'source1' as source
from &someNiceTable
where %sysfunc(dequote(&cond))
;
%mend;
请注意,这还将处理删除任何宏引号的问题,您可能会使用这些宏引号而不是文字引号字符来保护嵌入的逗号
请注意,对于COND变量,您可以只在条件周围添加()
,而不是使用引号或宏引号,以防止宏调用混淆
所以你的电话可能看起来像这样:
%DoStuff(col='col1, col3, col9',cond=(col1 = 12 or (col2 between 1 and 3)))
%DoStuff(col=%str(col1, col3, col9),cond=(col1 = 12 or (col2 between 1 and 3)))
我发现传递变量列表时最好在它们之间加空格,而不是逗号。这样,它们就可以在正常的SAS语句中直接使用。只有SQL提出了使用逗号作为分隔符的恼人要求。因此,让宏代码添加逗号,这样宏的用户就不必担心添加逗号了
%macro mymac(dsn,varlist);
%local sqllist;
%let sqllist=%sysfunc(translate(%sysfunc(compbl(&varlist)),%str(,),%str( )));
proc print data=&dsn ;
var &varlist ;
run;
proc sql ;
select &sqllist from &dsn ;
quit;
%mend mymac ;
您还可以使用其他字符(如|
或^
)作为值列表中的分隔符
%do i=1 %to %sysfunc(countw(&list,|));
%let word=%scan(&list,&i,|);
...
%end;
如果您将值作为带引号的字符串传递,并且希望在不带引号的情况下使用它们,则可以使用%SYSFUNC()
宏函数调用DEQUOTE()
函数
%MACRO DoStuff(col, cond);
select %sysfunc(dequote(&col))
, 'source1' as source
from &someNiceTable
where %sysfunc(dequote(&cond))
;
%mend;
请注意,这还将处理删除任何宏引号的问题,您可能会使用这些宏引号而不是文字引号字符来保护嵌入的逗号
请注意,对于COND变量,您可以只在条件周围添加()
,而不是使用引号或宏引号,以防止宏调用混淆
所以你的电话可能看起来像这样:
%DoStuff(col='col1, col3, col9',cond=(col1 = 12 or (col2 between 1 and 3)))
%DoStuff(col=%str(col1, col3, col9),cond=(col1 = 12 or (col2 between 1 and 3)))
我发现传递变量列表时最好在它们之间加空格,而不是逗号。这样,它们就可以在正常的SAS语句中直接使用。只有SQL提出了使用逗号作为分隔符的恼人要求。因此,让宏代码添加逗号,这样宏的用户就不必担心添加逗号了
%macro mymac(dsn,varlist);
%local sqllist;
%let sqllist=%sysfunc(translate(%sysfunc(compbl(&varlist)),%str(,),%str( )));
proc print data=&dsn ;
var &varlist ;
run;
proc sql ;
select &sqllist from &dsn ;
quit;
%mend mymac ;
您还可以使用其他字符(如|
或^
)作为值列表中的分隔符
%do i=1 %to %sysfunc(countw(&list,|));
%let word=%scan(&list,&i,|);
...
%end;
哇,这是有效的,我以前没有听说过这个%STR函数,我以前用过这个选择信息,这就是我离开它的原因。哇,这是有效的,以前没有听说过这个%STR函数,我以前用过这个选择信息,这就是我离开它的原因。