我在库调用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);
答案 0 :(得分:3)
首先,如果你只想要观察次数,你可以从dictionary.tables
或sashelp.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;
¯ocalls.;
假设您有一个宏%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循环)