SAS循环数据集

时间:2015-09-17 19:36:54

标签: sas

我在库调用snap1中有多个表:

cust1,cust2,cust3等

我想生成一个循环,该循环获取每个表中相同列的记录计数,然后将结果插入到不同的表中。

我想要的输出是:

Table Count

cust1 5,000
cust2 5,555
cust3 6,000

我正在尝试这个,但它不起作用:

%macro sqlloop(data, byvar);
proc sql noprint;
select &byvar.into:_values SEPARATED by '_'
from %data.;
quit;
data_&values.;
set &data;
select (%byvar);

%do i=1 %to %sysfunc(count(_&_values.,_));
%let var = %sysfunc(scan(_&_values.,&i.));
output &var.;
%end;
end;

run;
%mend;

%sqlloop(data=libsnap, byvar=membername);

2 个答案:

答案 0 :(得分:3)

首先,如果你只想要观察次数,你可以从dictionary.tablessashelp.vtable轻松获得,而不需要任何循环。

proc sql;
  select memname, nlobs
    from dictionary.tables
    where libname='SNAP1';
quit;

如果你没有做任何会导致逻辑观察数量不同的东西 - 通常是proc sql中的删除,这可以很好地检索行数。

其次,如果您对有效回复的数量感兴趣,那么也有更简单的非循环方式。

例如,假设您可以编写确定表名的任何查询,我们可以将它们全部放在set语句中并计入一个简单的数据步骤。

%let varname=mycol; *the column you are counting;
%let libname=snap1;


proc sql;
  select cats("&libname..",memname) 
    into :tables separated by ' '
    from dictionary.tables
    where libname=upcase("&libname.");
quit;

data counts;
  set &tables. indsname=ds_name end=eof; *9.3 or later;
  retain count dataset_name;
  if _n_=1 then count=0;
  if ds_name ne lag(ds_name) and _n_ ne 1 then do;
    output;
    count=0;
  end;
  dataset_name=ds_name;
  count = count + ifn(&varname.,1,1,0);  *true, false, missing;  *false is 0 only;
  if eof then output;
  keep count dataset_name;
run;

这种事物很少需要宏,而像你这样写的宏循环就更少了。

如果您确实想要编写宏,更简单的方法是:

  • 编写代码,对一个数据集执行一次
  • 在带有参数(数据集名称)
  • 的宏中包装
  • 根据需要为该宏创建宏调用

这样您就不必处理%scan并解决难以调试的宏代码问题。你写了一次有效的东西,然后多次调用它。

proc sql;
  select cats('%mymacro(name=',"&libname..",memname,')') 
    into :macrocalls separated by ' '
    from dictionary.tables
    where libname=upcase("&libname.");
quit;

&macrocalls.;

假设您有一个宏%mymacro,它可以为一个数据集做任何计算。

答案 1 :(得分:2)

  

*已更新*

将来,请发布日志,以便我们可以看到哪些内容无效。我可以在代码中看到一些问题,特别是在声明宏变量的地方,以及没有做任何事情的select语句。以下是实现目标的替代流程:

第1步:snap1库中的所有客户数据集读入宏变量:

proc sql noprint;
    select memname
    into :total_cust separated by ' '
    from sashelp.vmember
    where upcase(memname) LIKE 'CUST%'
          AND upcase(libname) = 'SNAP1';
quit;

第2步:计算每个数据集中的总数,输出到永久表:

 %macro count_obs;
      %do i = 1 %to %sysfunc(countw(&total_cust) );
           %let dsname = %scan(&total_cust, &i);

           %let dsid=%sysfunc(open(&dsname) );
           %let nobs=%sysfunc(attrn(&dsid,nobs) );
           %let rc=%sysfunc(close(&dsid) );

           data _total_obs;
                length Member_Name $15.;
                Member_Name = "&dsname";
                Total_Obs = &nobs;

                format Total_Obs comma8.; 
           run;

           proc append base=Total_Obs
                       data=_total_obs;
           run;
     %end;

     proc datasets lib=work nolist;
         delete _total_obs;
     quit;

 %mend;
 %count_obs;

如果永久表Total_Obs已存在,您将需要删除它,但如果您愿意,可以添加代码来处理它。

如果您想获取特定列的非缺失观察总数,请执行与上述相同的代码,但删除%let下面的3 %let dsname =个语句并替换{{1步骤:

data

(更新:修复了步骤2中的%do循环)