SAS Macro帮助循环每月sas数据集

时间:2017-11-13 13:10:59

标签: sas

我从2013年1月开始为客户提供SAS库中的月度数据集,数据集名称为CUST_JAN2013,CUST_FEB2013 ........ CUST_OCT2017。这些客户数据集每月拥有200万会员的巨大记录。这个月度数据集有两列(客户编号和客户每月费用)。

我有一个输入数据集Cust_Expense,其中客户编号和月份为列。此Cust_Expense表只有250,000个成员,并希望通过加入客户编号从SPECIFIC月度SAS数据集中提取每个成员的费用数据。

Cust_Expense
------------
Customer_Number  Month
111              FEB2014
987              APR2017
784              FEB2014
768              APR2017
.....
145              AUG2017
345              AUG2014

我尝试过使用call execute,但它尝试循环输入数据集的每个250,000条记录(Cust_Expense)并加入相应的每月SAS客户表,这需要花费太多时间。 有没有办法按月读取输入表(Cust_Expense),以便我们读取特定月份的所有客户,然后读取相同的每月表ONCE以从该月中提取所有记录,这样它就不会循环250,000次。 / p>

3 个答案:

答案 0 :(得分:1)

根据您想要的结果,您可以通过每月过滤cust_expenses并加入相应的每月数据集来创建每月一个输出

%macro want;
proc sql noprint;
select distinct month
into :months separated by ' '
from cust_expenses
;
quit;

proc sql;
%do i=1 %to %sysfunc(countw(&months));
  %let month=%scan(&months,&i,%str( ));
    create table want_&month. as
    select *
    from cust_expense(where=(month="&month.")) t1
    inner join cust_&month. t2
      on t1.customer_number=t2.customer_number
    ;
%end;
quit;
%mend;
%want;

或者,您可以通过将所有这些月度数据集“联合”为一个并动态添加月份列来使用一个联接输出一个输出。

%macro want;
proc sql noprint;
select distinct month
into :months separated by ' '
from cust_expenses
;
quit;

proc sql;
  create table want as
  select *
  from cust_expense t1
  inner join (
              %do i=1 %to %sysfunc(countw(&months));
                %let month=%scan(&months,&i,%str( ));
                %if &i>1 %then union;
                select *, "&month." as month
                from cust_&month
              %end;
             ) t2
    on t1.customer_number=t2.customer_number
     and t1.month=t2.month
  ;
quit;
%mend;
%want;

在任何一种情况下,我都没有真正看到将这些月度数据集与cust_expense数据集联系起来的重点。后者似乎没有保存月度数据集中尚未出现的任何信息。

答案 1 :(得分:1)

你的第一个,最好的答案是摆脱这些每月单独的表,并将它们放入一个ID和月份为关键的大表中。然后你可以简单地加入这个并继续前进。有这样的许多单独的表,其中数据元素确定他们所在的表是永远不是一个好主意。然后按月指数,使其更快。

如果你不能这样做,那么尝试创建一个所有这些表联合的视图。这样做可能会更快; SAS可能会决定实现视图,但可能不会(但如果它非常慢,那么请查看您的临时表空间,看看是否正在发生这种情况)。

然后第三个选项可能是使用SAS格式。使用CNTLIN option将较小的表格转换为格式。然后,单个大型datastep将允许您执行连接。

data want;
  set jan feb mar apr ... ;
  where put(id,CUSTEXPF1.) = '1';
run;

只有一次通过250k表,一次通过月表,加上非常快速的格式查找,这在数据步骤中无疑是零成本(因为磁盘i​​ / o会慢一些)。

答案 2 :(得分:-1)

我猜您可以在特定数据集中输出数据,例如:

data test;
infile datalines dsd;
   input ID : $2. MONTH  $3. ;
   datalines;
1,JAN
2,JAN
3,JAN
4,FEB
5,FEB
6,MAR
7,MAR
8,MAR
9,MAR
; 
run;

data  JAN FEB MAR;
set test;
if MONTH = "JAN" then output JAN;
if MONTH = "FEB" then output FEB;
if MONTH = "MAR" then output MAR;
run;

您将避免遍历所有ID(250000) 并且您将使用SAS的数据集声明

最后,您将获得包含相关ID的12 DATASET。

例如,如果您使用FEB2014,您将使用子字符串函数,数据集中的条件将变为:

...
set test;
...
if SUBSTR(MONTH,1,3)="FEB" then output FEB;
...

此致