使用PROC SQL在SAS中进行LEFT JOIN

时间:2014-05-14 08:52:13

标签: join sas left-join proc-sql

我是SAS的新手并且遇到了这个基本问题。我在表A中列出了纽约证券交易所的交易日期,如下所示 -

trading_date
1st March 2012
2nd March 2012
3rd March 2012
4th March 2012
5th March 2012
6th March 2012

我有另一张表B,其股价信息为 -

Date          ID    Ret Price
1st March 2012  1   …   …
3rd March 2012  1   …   …
4th March 2012  1   …   …
5th March 2012  1   …   …
6th March 2012  1   …   …
1st March 2012  2   …   …
3rd March 2012  2   …   …
4th March 2012  2   …   …

...包含与价格和退货相关的数字数据。

现在我需要将NYSE Data表连接到上表以获取下表 -

Date         ID    Ret  Price
1st March 2012  1   …   …
2nd March 2012  1   0   0
3rd March 2012  1   …   …
4th March 2012  1   …   …
5th March 2012  1   …   …
6th March 2012  1   …   …
1st March 2012  2   …   …
2nd March 2012  2   0   0
3rd March 2012  2   …   …
4th March 2012  2   …   …

即。一个简单的左连接。零将被填充。在SAS中表示缺失值,但是你明白了。但是,如果我使用以下命令 -

proc sql;
create table joined as
select table_a.trading_date, table_b.* from table_a LEFT OUTER join table_b on table_a.trading_date=table_b.date;
quit;

仅对第一个ID(即ID = 1)进行连接,而对于其余ID,则保持相同的数据。但我需要为所有ID插入交易日期。

如何在不为所有ID运行do while循环的情况下获取最终数据?由于内存有限,我有1000个ID并且循环并且加入1000次不是一个选项。

3 个答案:

答案 0 :(得分:5)

Joe是对的,你需要同时考虑ID,但是使用他的解决方案你不能得到2nd March 2012,因为当天没有人交易。只需一个sql步骤即可完成所有操作(这需要更长的时间):

proc sql;
   create table final as
   select d.trading_date, d.ID, t.Price, t.Ret
   from
   (
      select trading_date, ID 
      from table_a, (select distinct ID from table_b) 
   ) d
   left join
   (
      select *
      from table_b
   ) t
   on t.Date=d.trading_date and t.ID=d.ID
   order by d.id, d.trading_date;
quit;

答案 1 :(得分:1)

您的左连接不起作用,因为它不会考虑ID。 SAS(或者说SQL)并不知道它应该通过ID重复。

获得完整组合的最简单方法是PROC FREQ和SPARSE,假设某人在每个有效交易日都有交易。

proc freq data=table_b noprint;
tables id*trading_date/sparse out=table_all(keep=id trading_date);
run;

然后通过id和date将其连接到原始table_b。

或者,您可以使用PROC MEANS,它可以获得数字(它不能以这种方式获取字符,除非您可以将它们用作类值)。

使用Anton创建的table_b(包含retprice变量):

proc means data=table_b noprint completetypes nway;
class id trading_date;
var ret price;
output out=table_allmeans sum=;
run;

这将为当前行的缺失行和值输出缺失,并且将有一个_FREQ_变量,允许您区分行是否确实存在于交易数据集中。

答案 2 :(得分:-1)

我认为数据必须有一些东西,因为你的查询看起来很好,并且按照你所描述的方式处理我生成的测试数据:

data table_a;
    format trading_date date9.;
    do trading_date= "01MAR2012"d to "06MAR2012"d;
        output;
    end;
run;

data table_b;
    format date date9.;
    ret = 0;
    price = 0;
    do date= "01MAR2012"d to "06MAR2012"d;
        do ID = 1 to 4;
            if ranuni(123) < 0.3 then
                output;
        end;
    end;
run;

以下是我逐字复制运行查询后得到的内容:

trading_date date ret price ID 
01MAR2012 01MAR2012 0 0 3 
02MAR2012 02MAR2012 0 0 2 
03MAR2012 03MAR2012 0 0 1 
03MAR2012 03MAR2012 0 0 2 
04MAR2012 04MAR2012 0 0 2 
05MAR2012 05MAR2012 0 0 3 
06MAR2012 . . . . 

值得检查日期的格式 - 它们是数字吗?如果它们是角色,它们的格式是否相同?如果它们是数字的,它们的日期或日期时间是否应用了一些奇怪的格式?