z*****h 发帖数: 111 | 1 求助高手,在sas中经常需要以下操作
proc sql;
create table tb as select
a.*, b.val
from left a left join right b
on a.ID=b.ID
and 1<=intck('month', b.date, a.date)<=60;
quit;
这个方法很慢,看了下用hash,貌似只能实现equality join. 有想过用proc expand
把left表中的每一个date扩展成整个过去的60个月,然后用date step merge 或者
hash. 这样就能把inequality join 变成 equality join, 但是不知道怎么实现。
请教proc expand 的方法怎么实现,另外如果有更好的方法,请不吝赐教! | g****8 发帖数: 2828 | 2 楼主,我不是回答问题的。想请教一下,你那个And要是改成 where,这个 SQL结果会
有什么不同?
【在 z*****h 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 求助高手,在sas中经常需要以下操作 : proc sql; : create table tb as select : a.*, b.val : from left a left join right b : on a.ID=b.ID : and 1<=intck('month', b.date, a.date)<=60; : quit; : 这个方法很慢,看了下用hash,貌似只能实现equality join. 有想过用proc expand : 把left表中的每一个date扩展成整个过去的60个月,然后用date step merge 或者
| z*****h 发帖数: 111 | 3 会发生错误,如果用了left join 必须用on.
【在 g****8 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 楼主,我不是回答问题的。想请教一下,你那个And要是改成 where,这个 SQL结果会 : 有什么不同?
| h*******n 发帖数: 458 | 4 楼上问的是把这一句
and 1<=intck('month', b.date, a.date)<=60;
变成WHERE。我觉得是可以的,效率哪个更高就不清楚了。直觉上是WHERE效率高。
另外,把一个record复制多遍可以这样做:
data new;
set old;
do i=1 to Ntimes;
retain var1 var2 … varM;
output;
end;
run;
不过复制后的DATE还是原来的值,没变。你可以产生一个新的DATASET,含你MERGE要用
的ID var,每个弄若干行(60个月的天数),再加一个DATE,在和上面CODE类似的循环
里用INTNX产生要的日期。然后MERGE。
【在 z*****h 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 会发生错误,如果用了left join 必须用on.
| z*****h 发帖数: 111 | 5 那句也是不能用where, 而是必须在 on 里面。 不信你可以试试看。
【在 h*******n 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 楼上问的是把这一句 : and 1<=intck('month', b.date, a.date)<=60; : 变成WHERE。我觉得是可以的,效率哪个更高就不清楚了。直觉上是WHERE效率高。 : 另外,把一个record复制多遍可以这样做: : data new; : set old; : do i=1 to Ntimes; : retain var1 var2 … varM; : output; : end;
| S******3 发帖数: 66 | 6 actually, hash can do it with some trick. it's pretty fast and does not
require much temporary space.
some pseduo code for your reference (you need rename date variables first).
I think it worth some dollars, at least WB!
/* check to see if the current record has a match in the hash object */
rc = lookup.find(key: id);
/* if a match is found... */
if rc = 0 then do;
/* check the dates - if comparison is true, output the row */
if 1<=intck('month', date_b, date_a)<=60 then output;
/* check to see if there is another row in the hash object for the same
key */
lookup.has_next(result: r);
/* loop as long as there is another row in the hash object */
do while(r ne 0);
/* lookip to get the values from the next row in the hash object */
rc = lookup.find_next(key: id);
/* check the dates - if comparison is true, output the row */
if 1<=intck('month', date_b, date_a)<=60 then output;
/* check to see if there is another row in the hash object for the same
key */
lookup.has_next(result: r);
end;
end;
【在 z*****h 的大作中提到】![](/moin_static193/solenoid/img/up.png) : 求助高手,在sas中经常需要以下操作 : proc sql; : create table tb as select : a.*, b.val : from left a left join right b : on a.ID=b.ID : and 1<=intck('month', b.date, a.date)<=60; : quit; : 这个方法很慢,看了下用hash,貌似只能实现equality join. 有想过用proc expand : 把left表中的每一个date扩展成整个过去的60个月,然后用date step merge 或者
|
|