【发布时间】:2015-03-04 22:38:50
【问题描述】:
目标:从 Have 表 + Help 表到 Want 表。当前的实现(如下)很慢。我相信这是如何不使用 SAS 宏的一个很好的例子,但我很好奇是否...... 1. 宏观方法可以被挽救/变得足够快以使其可行 (例如 proc append 应该加快堆叠数据集的动作,但我看不到任何性能提升。) 2. 所有备选方案的外观。
我已经编写了一个非宏观解决方案,我将在下面发布以进行比较。
Data:
data have ;
input name $ term $;
cards;
Joe 2000
Joe 2002
Joe 2008
Sally 2001
Sally 2003
; run;
proc print ; run;
data help ;
input terms $ ;
cards;
2000
2001
2002
2003
2004
2005
2006
2007
2008
; run;
proc print ; run;
data want ;
input name $ term $ status $;
cards;
Joe 2000 here
Joe 2001 gone
Joe 2002 here
Joe 2003 gone
Joe 2004 gone
Joe 2005 gone
Joe 2006 gone
Joe 2007 gone
Joe 2008 here
Sally 2001 here
Sally 2002 gone
Sally 2003 here
; run;
proc print data=have ; run;
我可以为每个人编写一个小宏来让我到达那里:
%MACRO RET(NAME);
proc sql ;
create table studtermlist as
select distinct term
from have
where NAME = "&NAME"
;
SELECT Max(TERM) INTO :MAXTERM
FROM HAVE
WHERE NAME = "&NAME"
;
SELECT MIN(TERM) INTO :MINTERM
FROM HAVE
WHERE NAME = "&NAME"
;
CREATE TABLE TERMLIST AS
SELECT TERMS
FROM HELP
WHERE TERMS BETWEEN "&MINTERM." and "&MAXTERM."
ORDER BY TERMS
;
CREATE TABLE HEREGONE_&Name AS
SELECT
A.terms ,
"&Name" as Name,
CASE
WHEN TERMS EQ TERM THEN 'Here'
when term is null THEN 'Gone'
end as status
from termlist a left join studtermlist b
on a.terms eq b.term
;
quit;
%MEND RET ;
%RET(Joe);
%RET(Sally);
proc print data=HEREGONE_Joe; run;
proc print data=HEREGONE_Sally; run;
但它并不完整。如果我遍历 for(大概有很多名字)......
*******need procedure for all names - grab info on have ;
proc sql noprint;
select distinct name into :namelist separated by ' '
from have
; quit;
%let n=&sqlobs ;
%MACRO RETYA ;
OPTIONS NONOTEs ;
%do i = 1 %to &n ;
%let currentvalue = %scan(&namelist,&i);
%put ¤tvalue ;
%put &i ;
%RET(¤tvalue);
%IF &i = 1 %then %do ;
data base; set HEREGONE_¤tvalue; run;
%end;
%IF &i gt 1 %then %do ;
proc sql ; create table base as
select * from base
union
select * from HEREGONE_¤tvalue
;
drop table HEREGONE_¤tvalue;
quit;
%end;
%end ;
OPTIONS NOTES;
%MEND;
%RETYA ;
proc sort data=base ; by name terms; run;
proc print data=base; run;
所以现在我想要,但是有 6,000 个名字,需要 20 多分钟。
【问题讨论】:
-
HELP 数据集中的 TERMS 实际上是数字吗?它们是否像示例中那样连续?
-
不使用宏怎么办?
-
条款是故意的。实际术语可以包含多个零 (201000) 并存储为字符。
-
嗯...我的第一个解决方案假设相反。稍后我会再看一遍,但这取决于您的条款是如何存储的。
-
条款是故意的。实际术语可以包含多个零 (201000) 并存储为字符。它们是连续的……尽管规模不寻常:200000、200010、200015、20020、200050、200060……但这可以通过使用“帮助”表来处理。感谢您的回复,我期待有时间仔细检查它们。