如何根据时间和重叠的数值范围为数据集赋值? - SAS

How can I assign values to dataset based on time and overlapping numerical ranges? - SAS

我有一个信用卡交易数据集(我们称它为"Trans"),其中包含交易金额、邮政编码日期.我有另一个数据集(我们称之为 "Key"),它列出了基于 dategeocode 的销售税率。 Key 数据集还包括一系列与每个地理编码关联的邮政编码,由 2 个变量表示:Zip Start 和 Zip End。

由于地理编码与邮政编码不一致,因此部分邮政编码范围重叠。如果发生这种情况,我想使用与 Trans.

中显示的邮政编码关联的最低销售税率

反式数据集:

TransAmount TransDate TransZip
0 01/07/1998 90010
 02/09/2002 90022

关键数据集:

Geocode Rate StartDate EndDate ZipStart ZipEnd
1001 .0825 199701 200012 90001 90084
1001 .085 200101 200812 90001 90084
1002 .0825 199701 200012 90022 90024
1002 .08 200101 200812 90022 90024

期望的输出:

TransAmount TransDate TransZip Rate
0 01/07/1998 90010 .0825
 02/09/2002 90022 .08

我在 SAS 中使用了这个基本的 SQL 代码,但我 运行 遇到了重叠邮政编码的问题。

 proc sql;
 create table output as
 select a.*, b.zipstart, b.zipend, b.startdate, b.enddate, b.rate
 from Trans.CA_Zip_Cd_Testing a left join Key.CA_rates b
  on a.TranZip ge b.zipstart
  and a.TranZip le b.zipend
  and a.TransDate ge b.StartDate
  and a.transDate le b.EndDate
;
quit;

就查询部分而言,执行此操作的最简单方法是仅添加一个子查询以获得最低速率。

Select t.transamount, t.transdate,t.transzip
        ,(Select MIN(rate) from Key where t.transzip between ZipStart and ZipEnd and t.transdate between startdate and enddate) 'Rate'
from trans t

您也可以将它作为子查询并加入它。

SAS SQL 优化器有时会很好。其他时候,这可能是一个挑战。这段代码会有点复杂,但它可能会更快,并且受密钥 table.

的大小限制
data key;
set key;
   dummy_key=1;
run;

data want(drop=dummy_key geocode rate startDate endDate zipStart zipEnd rc i);
if _n_ = 1 then do;
 if 0 then set key;
 declare hash k (dataset:'key',multidata:'y');
 k.defineKey('dummy_key');
 k.defineData('geocode','rate','startdate','enddate','zipstart','zipend');
 k.defineDone();
end;
call missing (of _all_);
set trans;
dummy_key=1;

rc = k.find();
do i=1 to 1000 while (rc=0);
transZipNum = input(transZip,8.); *converts character zip to number. if its    already a number then remove;
zipStartNum = input(zipStart,8.);
zipEndNum = input(zipEnd,8.);

if startDate <= transDate <= endDate then do;
     if zipStartNum <= transZipNum <= zipEndNum then do;
          rate_out = min(rate_out,rate);
     end;
end;
rc=k.find_next();
end;
run;