我需要进行查询并在其中使用IN
语句。
首先我读了一个txt文件:
filename ticklist '/home/mypath/myfile.txt';
data sp500;
infile ticklist;
input smbl $;
smbl=upcase(smbl);
run;
这为变量sp500.smbl
提供了值AA, HNZ, ...
(超过500)。
然后我提出一个问题:
data result;
set mydata;
where also company_symbol IN (sp500.smbl);
run;
我总是得到众所周知的问题:
语法错误,期望以下之一:带引号的字符串,数字常量,日期时间常量,缺失值, - 。
如何使用带有IN
语句的字母数字变量?为什么它不能用它 - 是不是引用了字母数字字符串? IN
语句中需要什么样的数据结构?
答案 0 :(得分:2)
您可以使用proc sql执行此操作。您可能希望将trim和compress添加到company_symbol以确保空格不会破坏company_symbol和smbl之间的任何匹配
这将从mydata中选择所有字段,其中company_symbol与表sp500中的smbl匹配
proc sql noprint;
create table result as
select *
from mydata
where company_symbol in (select distinct smbl from sp500)
;
quit;
答案 1 :(得分:1)
首先,与您实际编写的内容最接近的方法是将术语括在引号中,将它们选择为宏变量,然后在数据步骤中使用它们:
proc sql;
select quote(smbl) into :smbllist separated by ' '
from sp500;
quit;
data result;
set mydata;
where company_symbol in (&smbllist.);
run;
这不是一个特别好的方法,但它确实有效。
备选方案:
数据步合并(或SQL Join)通常比相比更好,因为它更好地利用了hash / index / etc.
data result;
merge mydata(in=a) sp500(in=sp);
by company_symbol;
if a and sp;
run;
这要求对它们进行排序,并在两者中使用相同的变量名称(如果需要,可以在合并语句中的一个数据集上使用RENAME)。 SQL内部联接会做同样的事情,并且奖励不需要显式排序,尽管它可能会为您排序数据而不告诉您(因此不会节省时间)。取决于哈希解决方案是否有效(如果是,那么它不必排序)。
如果排序对您来说是一个额外的步骤(例如,如果它通常不按这种方式排序),格式通常会更快。
数据for_fmts; 设置sp500; fmtname =' $ SMBLF&#39 ;; 开始= SMBL; 标签=" 1&#34 ;; *或任何你想要的真实; 输出; 如果 n = 1则执行; HLO ='○&#39 ;; *这检查不匹配; 开始=' &#39 ;; 标签=' 0&#39 ;; *或任何你想要的虚假; 输出; 结束; 运行;
*必须是smbl的NODUPKEY,所以如果有重复项,请执行proc sort nodupkey;
proc格式cntlin = for_fmts; 退出;
数据结果; 设置mydata; put(company_symbol,$ SMBLF。)=' 1&#39 ;; 运行;
哈希表与面向对象思维方面的实际写法最接近。
data result;
if _n_=1 then do;
if 0 then set sp500;
declare hash sp('dataset:sp500');
sp.defineKey('smbl');
sp.defineData('smbl'); *or whatever you want to return when found, if something;
sp.defineDone();
call missing (smbl); *initialize to missing to avoid warning;
end;
set mydata;
rc = sp.find(key:company_symbol);
if rc eq 0 then output; *or you could do this in one statement, skipping the rc, just being clear here;
run;