由于宏变量的值的长度不能超过(65534)的最大长度,因此我无法为所有观察结果创建单个宏变量。我想创建一个宏来遍历我的数据集以生成几个数字列表,这些列表可以传递给proc sql中的where语句。
代替此:
*proc sql noprint;
select ID into :ParaList separated by ','
from work.ID_LIST(**firstobs=1 obs=5000**);
quit;*
*proc sql noprint;
select ID into :ParaList2 separated by ','
from work.ID_LIST(**firstobs=5001 obs=10000**);
quit;*
*proc sql noprint;
select ID into :ParaList3 separated by ','
from work.ID_LIST(**firstobs=10001 obs=15000**);
quit;*
*proc sql noprint;
select ID into :ParaList4 separated by ','
from work.ID_LIST(**firstobs=15001 obs=20000**);
quit;*
我想要类似的东西:
*proc sql noprint;
select ID into :List1-Last4 separated by ','
from work.ID_LIST(**firstobs=1 obs=&LASTOBS** BY 5000);
quit;*
我想创建一个宏来遍历每5000个观察值,直到最后一个观察值为止,以便我可以传递到where语句,例如(&ParaList,&ParaList2,&ParaList3,&ParaList4)中的where id。我知道还有
之类的替代方法id in (select id from work.table)
,但是在这种情况下,它不起作用。我正在通过SAS查询Hadoop,除传递宏变量列表外没有任何成功。
答案 0 :(得分:1)
您可以在Hadoop中创建临时表吗?将您的ID_LIST数据上传到临时表,然后在传递查询中使用它。
libname hdp hadoop noprompt="… connection parameters …";
libname hdp_temp hadoop noprompt="… connection parameters …" dbmstemp=yes;
proc delete data=hdp_temp.id_list;run;
data hdp_temp.id_list;
set work.my_id_list;
run;
* im not sure on the Hadoop side object naming patterns and default schemas,
* so this code shows dbo. as is the case in SQL Server;
* SAS libname option dmbstemp=yes for SQL Server causes created tables to be
* referenced as dbo.##<tablename>;
proc sql;
connect using hadoop;
create table work.susbset_of_big as
select * from connection to Hadoop
( select * from dbo.my_big_remote_table
where id in (select id from dbo.##id_list)
);
quit;
答案 1 :(得分:0)
您可以使用data step
do
循环和call execute()
来完成此操作。
data _null_;
set lib.id_list (nobs=totobs);
do i = 1 to totobs by 5000;
call execute(cat(
'proc sql;
select ID into :paralist', i,' separated by ','
from lib.id_list (firstobs=', i,
' obs=5000); quit;'
));
call execute(cats('%put |paralist',i,'|;'));
end;
run;
中的data step
函数调用
上面的调用生成了一行
proc sql;
select id into:paralist1 separated by ','
from lib.id_list (firstobs=1 obs=5000);
quit;
proc sql;
select id into:paralist5001 separated by ','
from lib.id_list (firstobs=5001 obs=5000);
quit;
/* etc */
答案 2 :(得分:0)
您可以轻松地使用数据步骤来生成宏变量。您还应该生成一个宏变量,该宏变量调用所有其他宏变量。
%let n_per_list=5 ;
data _null_;
length idlist $32000;
length macrolist $1000 ;
retain macrolist;
do i=1 to &n_per_list until (eof);
set id_list end=eof;
idlist=catx(',',idlist,id);
end;
listno+1;
call symputx(cats('paralist',listno),idlist);
macrolist=catx(',',macrolist,cats('&','paralist',listno));
call symputx('paralist',macrolist);
run;
对于将20个值分为5组的简单测试,将得出以下结果:
151 %put Paralist=%superq(ParaList);
Paralist=¶list1,¶list2,¶list3,¶list4
152 %put &=Paralist1;
PARALIST1=1,2,3,4,5
153 %put &=Paralist;
PARALIST=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
或者您可以只看将代码生成到宏中,而不使用宏变量。列表可以生成多长时间应该没有任何限制。您可以尝试找出如何在宏内部打开数据集而不生成任何SAS代码的方法,以便宏调用的结果只是值列表。但是,将宏定义的源代码生成到文件然后%include文件来定义它会容易得多。
filename code temp;
data _null_;
set id_list end=eof;
file code lrecl=80;
if _n_=1 then put '%macro paralist;' ;
else put ',' @ ;
put id @ ;
if eof then put / '%mend paralist;' ;
run;
相同的20个值列表的结果。
163 %include code / source2;
NOTE: %INCLUDE (level 1) file CODE is file /.../#LN00043.
164 +%macro paralist;
165 +1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 ,19 ,20
166 +%mend paralist;
NOTE: %INCLUDE (level 1) ending.
167 %put %paralist;
1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 ,19 ,20
答案 3 :(得分:0)
我喜欢@Richard解决方案,它将使它更加干净高效。如果您的数据集不是很大,您也可以尝试隐式传递。
Libname SASTAB "yoursaslocation";
Libname HTAB your hadoop parameters;
proc sql;
create HTAB.newtable as
select * froom HTAB.yourtable
where id in (Select id from SASTAB.yoursastable);