在 SAS 中查找第二个最晚日期

Posted

技术标签:

【中文标题】在 SAS 中查找第二个最晚日期【英文标题】:Finding the second latest date in SAS 【发布时间】:2015-11-20 00:43:56 【问题描述】:

我有两列:

GRP_ACCT_NO,TRANS_DATE

数据是关于不同账户进行的交易。因此,GRP_ACCT_NO 具有重复值,而 TRANS_DATE 给出了该特定帐户进行交易的日期。我在数据集中有大约 150 万条记录,但只有 97k 个唯一帐户。我想在 SAS 中查找每个帐户的第二个最新交易日期

这是我尝试过的代码:

proc sql;
  create table second_latest_trans as
  select GRP_ACCT_NO,Max(TRANS_DATE) from project.spend as ps
  where TRANS_DATE < (select max(TRANS_DATE) 
                      from project.spend as ps2 
                      where ps.GRP_ACCT_NO = ps2.GRP_ACCT_NO 
                      group by GRP_ACCT_NO)
  group by GRP_ACCT_NO;
quit;

代码似乎没有得到任何结果。加载需要很长时间。

请帮忙!!

【问题讨论】:

【参考方案1】:

SQL 没有观察顺序的概念。使用 DATA 步。如果您的数据尚未排序,请对其进行排序(创建索引)。

如果您只想要第二条记录,即使有平局,您也可以只计算每个帐户的记录。

data second_latest_trans;
  set project.spend;
  by GRP_ACCT_NO TRANS_DATE;
  if first.grp_acct then recno=0;
  recno+1;
  if recno=2 then output;
run;

如果 TRANS_DATE 的相同值有多个记录,并且您想要 TRANS_DATE 的第二个不同值,那么这个更复杂的步骤会起作用。

data second_latest_trans;
  set project.spend;
  by GRP_ACCT_NO TRANS_DATE;
  if first.grp_acct then found=0;
  else if not found and first.trans_date then do;
     output;
     found=1;
  end;
  retain found;
run;

【讨论】:

嗨,对不起,我认为我的问题不清楚。我现在改写了。我想要的是帐号以及他们的第二次最新交易。所以,基本上,我的新数据集应该有大约 97k 条记录。当我尝试上面的代码时,我得到了 130 万条记录。【参考方案2】:

您的查询(除了格式)看起来很合理。我想知道子查询中的group by 是不是把事情搞砸了。试试这个版本:

proc sql;
create table second_latest_trans as
    Select GRP_ACCT_NO, Max(TRANS_DATE)
    from project.spend ps
    where TRANS_DATE < (SELECT max(ps2.TRANS_DATE)
                        from project.spend ps2
                        where ps.GRP_ACCT_NO = ps2.GRP_ACCT_NO
                       )
   group by GRP_ACCT_NO;
quit;

如果您希望它运行得更快,您需要在project.spend(GRP_ACCT_NO, TRANS_DATE) 上建立索引。数据步骤解决方案(在另一个答案中提出)可能会快得多。

【讨论】:

【参考方案3】:

SAS SQL 不是处理序列问题的好工具。如果你想找到组中第二高或低的记录,也许你可以试试这个。我以班级为例,在每组中找到第二个体重的人。方法是先从组中删除体重最高的人,然后选择体重最高的人,但是,它可以处理并列体重。希望能给你一些想法。

proc sql;
  select * from (select * from sashelp.class where weight not in 
  (select weight from sashelp.class group by age having weight=max(weight))) 
  group by age having weight=max(weight);
quit;

【讨论】:

【参考方案4】:
data test;
set spend;
run;

按 acct_no 排序,因此最大的日期在最前面。

proc sort data=test;
by grp_acct_no trans_date descending;
run;

删除与最近日期对应的记录

data test2;
set test;
by grp_acct_no trans_date;
if first.grp_acct_no =1  and first.trans_date =1  then delete;
run;

现在每个 acct_no 对应的第一条记录是第二大日期,因为删除了最大的日期。删除除此记录之外的所有内容。

data test3;
set test2;
by grp_acct_no trans_date;
if Not (first.grp_acct_no =1  and first.trans_date =1 ) then delete;

run;

test3 是最终的数据集

【讨论】:

【参考方案5】:

您可以使用retain 一次性遍历数据:

数据要; 设置有; 通过 GRP_ACCT_NO TRANS_DATE ; 保留 T1 T2 。 ; 如果 first.GRP_ACCT_NO 然后调用 missing(T1,T2) ; 如果 TRANS_DATE > T1 然后做; T2 = T1 ; T1 = TRANS_DATE ; 结尾 ; 如果最后一个.GRP_ACCT_NO ; 格式 T1 T2 date9。 ; 跑 ;

T1 是最新的 TRANS_DATE,T2 是之前的。

【讨论】:

以上是关于在 SAS 中查找第二个最晚日期的主要内容,如果未能解决你的问题,请参考以下文章

在正则表达式中查找字符串(日期)的倒数第二个出现

查找每个 ID 的特定日期之前的最大日期和特定日期之后的最小日期 [关闭]

Oracle Join 表与第一个表中的日期范围和第二个表中的日期

使用 string[] 在 XmlNode 中查找最新日期

从彼此相差不超过 x 分钟的日期中选择最晚的日期

如何查看员工在部门最晚生效日期是不是为部门经理?