没有proc SQL的模糊连接

时间:2018-02-05 15:27:14

标签: merge sas fuzzyjoin

美好的一天,

我希望将两个日期合并到下一个最近的

数据集是500M到1G,所以proc sql是不可能的。

我有两个数据集。第一个(舰队)有观察,第二个有日期,哪个世代号用于进一步处理。像这样:

data Fleet
    CreatedPortalDate 
    2013/2/19 
    2013/8/22 
    2013/8/25 
    2013/10/01 
    2013/10/07 

data gennum_list
    date 
    01/12/2014 
    08/12/2014 
    15/12/2014 
    22/12/2014 
    29/12/2014 
    ...

我想要的是这样的链接表:

data link_table
    CreatedPortalDate date 
    14-12-03  01/12/2014 
    14-12-06  01/12/2014 
    14-12-09  08/12/2014 
    14-12-11  08/12/2014 
    14-12-14  08/12/2014 

逻辑

Date < CreatedPortalDate and (CreatedPortalDate - date) = min(CreatedPortalDate - date)

我想出的是有点笨重,我正在寻找一种有效/更好的方法来实现这一目标。

data all_comb; 
  set devFleet(keep=createdportaldate);
  do i=1 to n;
    set gennum_list(keep=date) point=i nobs=n;
    if createdportaldate > date 
        and createdportaldate - 15 < date then do;/*Assumption, the generations are created weekly.*/
           distance= createdportaldate - date; 
          output; 
        end;
  end;
run;

proc sort data=all_comb; by createdportaldate distance; run;

data link_table; 
    set _all_comb(drop=distance); 
    by createdportaldate; 
    if first.createdportaldate; 
run;
  • 有关如何改进或解决此问题的任何想法?
  • 无知的想法:我可以创建存储distance的哈希表吗?
  • 阵列可能吗?不知。

编辑:

  • 通用格式
    • 完成
  • 十亿行来自哪里?
    • 是的,还有其他数据,但日期是唯一的链接变量。
  • 排序
    • 是的,数据已排序,可以再次排序。
  • 生成日期总是相隔七天吗?
    • 否。这是棘手的部分。否则,我可以使用weekyear(或其他分箱)作为唯一标识符。

2 个答案:

答案 0 :(得分:0)

巨大是一个相对的术语,今天的巨大是明天的特色。

关键数据功能表明直接寻址查找方案是可能的

  • 日期值为整数。
  • 日期值范围有限。
  • 日期值或接下来14天中的任何一天将用作查找验证程序
  • 键是日期值,可用作数组索引。

按如下方式加载Gennum查找一次

array gennum_of ( %sysfunc(today()) ) _temporary_;
if last_date then
  do index = last_date to date-1;
    gennum_of(index) = prev_date;
  end;

last_date = date;

取一个gennum为

if portaldate > last_date
  then portal_gennum = last_date;
  else portal_gennum = gennum_of ( portaldate );

如果由于按帐户ID分组而有很多行,则必须清除并加载每个组的gennum数组。

答案 1 :(得分:0)

这是sas by语句的典型应用程序。

by步骤中的data语句用于读取一个按公共变量排序的两个或多个数据集。

公共变量是日期,但在两个数据集上的命名方式不同。在sql中,您可以通过要求将一个变量与另一个变量Fleet.CreatedPortalDate = gennum_list.date相等来解决这个问题,但by语句不允许这样的构造,因此我们必须重命名(至少)一个他们在阅读数据集时。我们在rename

选项中的gennum_list子句中执行此操作
data all_comb;
    merge gennum_list (in = in_gennum rename = (date = CreatedPortalDate))
          Fleet (in = in_fleet);
    by CreatedPortalDate;

我选择将by语句与merge语句结合起来,虽然set也可以完成这项工作,但两个输入数据集的顺序都有所不同。< / p>

另请注意,我请求sas创建指标变量in_gennumin_fleet,以指示值存在于哪个输入数据集中。知道这种类型的变量不会写入结果数据集是很方便的。

但是,我们必须从date恢复CreatedPortalDate,当然

    if in_gennum then date = CreatedPortalDate;

如果您是sas的新手,您会惊讶于上述陈述不起作用除非您明确指示sas retain从一个观察到巢的日期值。 (观察是行的行话。)

    retain date;

在这里,我们为从Fleet数据集中读取的每个观察值写出一个观察值。

    if in_fleet then output;
run;

这种方法的优点是

  • 您需要更少的逻辑来正确组合来自两个输入数据集的观察结果(这就是data步骤的发明)
  • 您永远不必在内存中保留一组值,因此您不会遇到溢出问题
  • 这个sollution的数量级为1(O1),数据集的大小(除了排序),所以我们事先知道,数据量加倍只会使时间加倍。

    免责声明:此答案正在制定中。

将在本周晚些时候进行测试