Macros SAS宏传递要在宏中使用的SQL或代码

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子句作为第二个参数传

我对SAS宏编程比较陌生,我主要使用它使我的代码“更干净”,避免重复代码中的错误

我做了一些谷歌搜索,但并没有找到简单的方法

首先我有两个问题-如何将列列表传递给宏

我想让宏在一般代码中看起来像这样:

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函数,我以前用过这个选择信息,这就是我离开它的原因。