按ID提取首个Y类型记录日期作为起始日期的实现问题
问题描述
给定按ID和日期排序的数据集:
id type date 1 Y 01/01/2022 1 Y 09/01/2022 1 X 12/01/2022 2 Y 08/01/2022 2 X 09/01/2022 2 X 12/01/2022
需求:将每个ID下第一条Y类型记录的日期设为该ID所有记录的Start日期,预期结果如下:
id type date Start 1 Y 01/01/2022 01/01/2022 1 Y 09/01/2022 01/01/2022 1 X 12/01/2022 01/01/2022 2 Y 08/01/2022 08/01/2022 2 X 09/01/2022 08/01/2022 2 X 12/01/2022 08/01/2022
尝试过用do until循环查找最早的Y类型事件,但不知道如何关联到对应日期,求解决方法。
解决方案1:SQL窗口函数(通用)
用窗口函数FIRST_VALUE()结合分区和条件筛选,直接为每个ID提取第一条Y的日期:
SELECT id, type, date, FIRST_VALUE(CASE WHEN type = 'Y' THEN date END) OVER ( PARTITION BY id ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS Start FROM your_table ORDER BY id, date;
核心逻辑:
PARTITION BY id:按ID分组处理每个单独的用户/实体ORDER BY date:确保按日期顺序定位最早的Y类型记录CASE WHEN type='Y' THEN date END:仅保留Y类型的日期值,非Y记录的位置为NULLFIRST_VALUE()会在分组内取第一个非NULL的日期,也就是该ID最早的Y类型日期
解决方案2:SAS数据步(适配do until思路)
如果用SAS处理,不需要复杂循环,用BY组关联更高效:
方法一:临时表合并法
/* 第一步:提取每个ID的第一条Y类型日期 */ data temp_start; set have; by id; if type = 'Y' and first.id then output; keep id date; run; /* 第二步:将原表和临时表按ID合并 */ data want; merge have temp_start(rename=(date=Start)); by id; format date Start ddmmyy10.; run;
方法二:do until循环实现
data want; set have; by id; retain Start; /* 每个ID的第一条记录时初始化Start */ if first.id then do; Start = .; /* 循环查找当前ID下第一条Y类型记录 */ do until (type = 'Y' or last.id); set have(keep=id type date) point=_n_; if type = 'Y' then do; Start = date; leave; end; _n_ + 1; end; /* 如果当前行就是该ID的第一条Y,直接赋值 */ if type = 'Y' and Start = . then Start = date; end; format date Start ddmmyy10.; run;
内容的提问来源于stack exchange,提问作者geek45
相关产品推荐
相关产品推荐

