PAYATHON 2026

按 account_number 判断日期是否位于两个日期之间

数据阿明

结论

先按 acct_num 和 biiling_date 排序,每个账户只保留日期最早的两条记录。再用这两条记录的 billing cycle date 确定区间上下界,检查 tran_date 是否落在区间内。账户必须至少有两次 billing cycle,且交易日期在区间内,才会保留这两条记录。

SAS 实现

先确保日期已读取为 SAS 日期值,而不是字符:

data have;
    input acct_num
          biiling_date :date9.
          tran_date    :date9.;

    format biiling_date tran_date date9.;

    datalines;
1111 23FEB2020 27FEB2020
1111 23MAR2020 27FEB2020
2222 17MAR2020 22MAR2020
2222 27APR2020 22MAR2020
2222 27MAY2020 22MAR2020
3333 23JUL2018 02JUN2022
3333 23AUG2018 02JUN2022
;
run;

1. 按账户和 billing cycle date 排序

proc sort data=have out=have_sorted;
    by acct_num biiling_date;
run;

这里将“前两次 occurrence”理解为日期最早的两次。如果 occurrence 指原始数据中的行顺序,应先创建行号,再按行号排序,而不是按 biiling_date 排序。

2. 每个账户只保留前两条记录

data first_two;
    set have_sorted;
    by acct_num;

    if first.acct_num then occurrence = 0;
    occurrence + 1;

    if occurrence <= 2;
run;

进入新账户时,occurrence 会重置。因此,账户 2222 的第三条记录会在这一步被删除。

3. 确定区间并筛选账户

proc sql;
    create table want as
    select a.acct_num,
           a.biiling_date,
           a.tran_date
    from first_two as a
    inner join
    (
        select acct_num,
               min(biiling_date) as start_date format=date9.,
               max(biiling_date) as end_date   format=date9.
        from first_two
        group by acct_num
        having count(*) = 2
    ) as b
        on a.acct_num = b.acct_num
    where a.tran_date between b.start_date and b.end_date
    order by a.acct_num, a.biiling_date;
quit;

结果如下:

1111  23FEB2020  27FEB2020
1111  23MAR2020  27FEB2020
2222  17MAR2020  22MAR2020
2222  27APR2020  22MAR2020

为什么 account 3333 会被删除

账户 3333 的日期区间是:

23JUL2018 至 23AUG2018

它的 tran_date 是 02JUN2022,不在这个区间内,所以连接后的两条记录都不满足 WHERE 条件。

注意事项

  • SAS 日期必须是数值型日期。如果原始字段是字符,需要先用 input(character_date, date9.) 转换。

  • BETWEEN 包含两个边界,相当于:

    start_date <= tran_date <= end_date
  • 账户至少需要有两条记录。having count(*) = 2 会排除只有一次 billing cycle 的账户。

  • 这段代码以同一账户的 tran_date 保持一致为前提。如果同一账户可能有多个不同的 tran_date,需要进一步确定是逐行判断,还是只要任意一个交易日期落入区间,就保留该账户的前两条记录。

  • 字段名沿用了示例中的 biiling_date。如果实际字段名是 billing_date,需要统一替换。

备注:内容仅供参考。