在字母数字字符串变量上使用IN语句

时间:2013-11-11 19:57:35

标签: sas

我需要进行查询并在其中使用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语句中需要什么样的数据结构?

2 个答案:

答案 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;