You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SAS DI Studio识别30天内重复申报同一费用类型的员工

解决同一员工同费用类型30天内重复采购的标记问题

嘿,这个重复采购标记的需求我很熟悉,刚好可以用SAS或者SQL来解决,结合你用SAS Data Integration Studio的场景,我给你准备了两种靠谱的实现方案,都能精准找出同一员工、同一费用类型且日期间隔30天内的记录,还能给它们打上RepeatPurchase='Y'的标识。

核心思路

要实现这个需求,关键是按员工编号(StaffNo)和费用类型(ExpenseType)分组,然后检查每组内的记录是否存在与其他记录的购买日期间隔≤30天的情况。需要注意:

  • 原始日期是字符型(比如01JAN2015),必须先转换成可计算的日期格式
  • 要排除记录自身和自身匹配的情况(比如同一条记录的日期差为0)
  • 不管记录顺序如何,只要组内存在符合条件的相邻或非相邻记录,都要标记

方案1:SAS PROC SQL实现

这种方案适合在DI Studio里用SQL节点快速实现,逻辑清晰,处理大数据量也高效:

/* 转换日期格式并标记重复采购记录 */
PROC SQL;
    CREATE TABLE flagged_expenses AS
    SELECT 
        a.*,
        /* 判断是否存在同员工同费用类型、日期间隔1-30天的其他记录 */
        CASE WHEN EXISTS (
            SELECT 1 
            FROM your_source_table b
            WHERE a.StaffNo = b.StaffNo
              AND a.ExpenseType = b.ExpenseType
              AND a.InvoiceNumber NE b.InvoiceNumber  /* 排除同一张发票的重复行,不需要可删除 */
              AND ABS(INPUT(a.Date, date9.) - INPUT(b.Date, date9.)) BETWEEN 1 AND 30
        ) THEN 'Y' ELSE 'N' END AS RepeatPurchase
    FROM your_source_table a;
QUIT;

代码解释

  1. INPUT(a.Date, date9.):把字符型的日期转换成SAS可识别的日期数值,date9.格式对应ddMONyyyy(比如01JAN2015)
  2. EXISTS子查询:检查当前记录是否有符合条件的“配对记录”,只要存在就标记为Y
  3. InvoiceNumber NE b.InvoiceNumber:避免同一条发票的重复记录被误判,如果你允许同一天同发票的情况,可以去掉这个条件

方案2:SAS数据步实现

如果习惯用数据步处理,这种排序+前后值对比的方式也很直观,适合需要可视化处理流程的场景:

/* 第一步:按员工、费用类型、日期排序,确保同组记录按时间排列 */
PROC SORT DATA=your_source_table;
    BY StaffNo ExpenseType INPUT(Date, date9.);
RUN;

/* 第二步:计算前后日期差,标记重复采购 */
DATA flagged_expenses;
    SET your_source_table;
    BY StaffNo ExpenseType;
    
    /* 转换字符日期为SAS日期值 */
    sas_date = INPUT(Date, date9.);
    
    /* 取上一条同组记录的日期 */
    lag_sas_date = LAG(sas_date);
    /* 取下一条同组记录的日期 */
    lead_sas_date = LEAD(sas_date);
    
    /* 判断:和前一条间隔≤30天,或者和后一条间隔≤30天,就标记Y */
    IF (NOT FIRST.ExpenseType AND sas_date - lag_sas_date <= 30) OR
       (NOT LAST.ExpenseType AND lead_sas_date - sas_date <= 30) THEN
        RepeatPurchase = 'Y';
    ELSE
        RepeatPurchase = 'N';
    
    /* 清理临时变量 */
    DROP sas_date lag_sas_date lead_sas_date;
RUN;

代码解释

  1. PROC SORT:先把数据按员工、费用类型、日期排序,这样同组的记录按时间顺序排列
  2. LAG()和LEAD()函数:分别获取当前记录的上一条和下一条同组记录的日期
  3. FIRST.ExpenseType和LAST.ExpenseType:判断当前记录是否是组内第一条或最后一条,避免越界计算

方案3:通用SQL实现(适用于DI Studio的SQL转换节点)

如果你的DI Studio支持通用SQL语法(比如对接其他数据库),可以用下面的写法,注意日期转换函数根据数据库调整:

SELECT 
    a.*,
    CASE WHEN EXISTS (
        SELECT 1 
        FROM your_source_table b
        WHERE a.StaffNo = b.StaffNo
          AND a.ExpenseType = b.ExpenseType
          AND a.InvoiceNumber != b.InvoiceNumber
          /* 日期转换函数根据数据库调整:下面是SQL Server的写法 */
          AND ABS(DATEDIFF(DAY, CONVERT(DATE, a.Date, 106), CONVERT(DATE, b.Date, 106))) BETWEEN 1 AND 30
    ) THEN 'Y' ELSE 'N' END AS RepeatPurchase
FROM your_source_table a;

注意事项

  • 日期转换函数:不同数据库的写法不同,比如MySQL用STR_TO_DATE(a.Date, '%d%b%Y'),Oracle用TO_DATE(a.Date, 'DDMONYYYY')
  • 如果允许同一天的重复记录,把BETWEEN 1 AND 30改成BETWEEN 0 AND 30

内容的提问来源于stack exchange,提问作者B.Dick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 06:48:57