proq sql宏;循环列表

时间:2016-09-02 12:30:47

标签: sas sas-macro

我有一个宏来查找给定数据集中的变量名称。如果缺少宏正在查找的变量名称,则缺少的变量名称将添加到表中:

%macro miss(ds, var);
    %local rc dsid result;
    %let dsid=%sysfunc(open(&ds));
    %if %sysfunc(varnum(&dsid,&var)) > 0 %then %do;
        %put &var present;
    %end;
    %else %do;
        insert into work.compare(missing) values("&var")
    %end;
%mend;

proc datasets library=work nolist nodetails;
    delete compare;
run;

proc sql;
    create table work.compare (missing char(15));
%miss(ctr.panup_in, u_name);
quit;

proc print noobs data=work.compare;
run;

需要针对55个不同的变量名运行此检查。目前,我只将每一个列为

%miss(ctr.panup_in, varname);

线。

出于实际原因,我想将变量列表指定为列表,例如%let dictionary = var1 var2 var3等。我现在的斗争是找到宏循环变量列表的方法。到目前为止,我所尝试过的所有内容都会导致“#st; Stament”无效"

的错误
insert into work.compare(missing) values("&var")

命令。

有没有人对如何做到这一点有任何建议?

4 个答案:

答案 0 :(得分:1)

这循环了一组变量所在的变量 用“|”分隔。可以使用任何其他分隔符 并在扫描功能中指定。

%macro loop(varlist);
%let i=1;
%do %while (%scan(&varlist, &i, |) ^=%str());
%let var=%scan(&varlist, &i, |); 
%put &var;

*rest of SAS code goes here;

*Increment counter;
%let i=%eval(&i+1);
%end;
%mend;
%let temp=a|b|c|d|e;
%loop(&temp);

答案 1 :(得分:1)

你真的需要检查吗?您可以定义要删除的所有变量的零obs数据集,如果它们丢失则使用未执行的SET来包含它们。

*All variables that you might want to add;
data master0;
   attrib a length=8;
   attrib b length=$15;
   attrib c length=$15;
   stop;
   call missing(of _all_);
   run;

*Subset of the variable in master0;
data a;
   do a = 1 to 10;
      output;
      end;
   retain X 1;
   run;

*Create new data with master + a variables;
data a_all;
   set a;
   if 0 then set master0;
   run;
proc print;
   run;

您可以使用修改来删除您不想要的变量,以便使用所有变量更新到主数据库。

*Create new data with with only wanted variables from master0;
data a_all;
   stop;
   set master0;
   run;
data a_all;
   if 0 then modify a_all;
   set a;
   output;
   run;

答案 2 :(得分:1)

另一个选择是让你的变量存储在一个表中 - 它们可能已经存在于一个表中。也许是dictionary.columns?

事实上,你可以通过dictionary.columns简单地完成整个过程。例如:

%let varlist=name age novar;

data values_to_check;
  length name $32;
  do _i = 1 to countw("&varlist.");
    name= scan("&varlist.",_i);
    output;
  end;
run;


proc sql;

  create table compare as
    select V.name as missing
    from values_to_check V
    left join
     (Select * from dictionary.columns 
      where memname='CLASS' and libname='SASHELP') D      
      on upcase(V.name)=upcase(D.name)
    where D.name is null
    ;
  quit;

如果您不必创建数据集(如果它已经存在),那么这当然更容易 - 或者作为另一个数据集中存在的变量列表,或者直接通过数据线或类似物创建数据集。可能的情况是,您有一些具有此信息的数据,而不仅仅是硬编码的%let语句。

一个示例,用于标识CLASSFIT中不在CLASS中的变量(均位于SASHELP库中):

proc sql;    
  create table compare as
    select V.name as missing
    from  
      (Select * from dictionary.columns 
      where memname='CLASSFIT' and libname='SASHELP')  V
    left join
     (Select * from dictionary.columns 
      where memname='CLASS' and libname='SASHELP') D      
      on upcase(V.name)=upcase(D.name)
    where D.name is null
    ;
  quit;

答案 3 :(得分:0)

如果您真的想要一个名称不在数据集中的表,那么您可以使用数据步骤并消除使用宏或PROC SQL的复杂性。

%let ds=sashelp.class;
%let varlist=age sex gender ;
data compare;
  length missing $32 ;
  dsid=open("&ds");
  do i=1 to countw("&varlist");
    missing = scan("&varlist",i);
    if not varnum(dsid,missing) then output;
  end;
  rc=close(dsid);
  stop;
  keep missing;
run;

现在,宏解决方案可能有用的地方是,如果您想传入列表并获取另一个列表,而不生成任何代码。

%macro miss(ds, varlist);
%local dsid i var result;
%let dsid=%sysfunc(open(&ds));
%if (&dsid) %then %do;
  %do i=1 %to %sysfunc(countw(&varlist));
    %let var=%scan(&varlist,&i);
    %if not %sysfunc(varnum(&dsid,&var)) %then %let result=&result &var;
  %end;
  %let rc=%sysfunc(close(&dsid));
%end;
%else %let result=&varlist;
&result.
%mend miss;

这样你就可以在语句中间调用宏,就像函数调用一样。

%put Missing variables are: %miss(sashelp.class,age sex gender);