proq sql 宏;遍历列表
proq sql macro; loop through list
我有一个在给定数据集中查找变量名称的宏。如果宏正在寻找的变量名丢失,丢失的变量名将添加到 table:
%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 等。我现在的努力是找到一种方法让宏循环遍历变量列表.到目前为止,我尝试过的所有操作都会导致
的 "Stament is not valid" 错误
insert into work.compare(missing) values("&var")
命令。
有人对如何执行此操作有任何建议吗?
这个循环遍历一组变量,其中变量
以“|”分隔。可以使用任何其他分隔符
并在扫描功能中指定。
%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);
你真的需要检查吗。如果缺少要添加的所有变量,您可以定义一个零 obs 数据集,并使用未执行的 SET 来包含它们。
*All variables that you might want to add;
data master0;
attrib a length=8;
attrib b length=;
attrib c length=;
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;
另一种选择是将您的变量存储在 table 中 - 很可能它们已经在其中了。也许 dictionary.columns?
事实上,您很可能可以通过 dictionary.columns 简单地完成整个过程。例如:
%let varlist=name age novar;
data values_to_check;
length name ;
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;
如果您真的想要 table 的名称不在您的数据集中,那么您可以只使用数据步骤并消除使用宏或 PROC 的复杂性 SQL.
%let ds=sashelp.class;
%let varlist=age sex gender ;
data compare;
length missing ;
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);
我有一个在给定数据集中查找变量名称的宏。如果宏正在寻找的变量名丢失,丢失的变量名将添加到 table:
%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 等。我现在的努力是找到一种方法让宏循环遍历变量列表.到目前为止,我尝试过的所有操作都会导致
的 "Stament is not valid" 错误insert into work.compare(missing) values("&var")
命令。
有人对如何执行此操作有任何建议吗?
这个循环遍历一组变量,其中变量 以“|”分隔。可以使用任何其他分隔符 并在扫描功能中指定。
%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);
你真的需要检查吗。如果缺少要添加的所有变量,您可以定义一个零 obs 数据集,并使用未执行的 SET 来包含它们。
*All variables that you might want to add;
data master0;
attrib a length=8;
attrib b length=;
attrib c length=;
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;
另一种选择是将您的变量存储在 table 中 - 很可能它们已经在其中了。也许 dictionary.columns?
事实上,您很可能可以通过 dictionary.columns 简单地完成整个过程。例如:
%let varlist=name age novar;
data values_to_check;
length name ;
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;
如果您真的想要 table 的名称不在您的数据集中,那么您可以只使用数据步骤并消除使用宏或 PROC 的复杂性 SQL.
%let ds=sashelp.class;
%let varlist=age sex gender ;
data compare;
length missing ;
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);