SAS如何统计十月每位学生至少借阅1本书的非重叠总天数
解法思路
- 第一步:统一日期格式,同时将所有借阅区间的边界限制在2021年10月范围内:早于2021-10-01的借阅日期统一调整为2021-10-01,晚于2021-10-31的归还日期统一调整为2021-10-31,过滤掉完全不在10月的无效借阅记录。
- 第二步:按学生分组,对所有借阅区间做合并操作,将重叠、相邻的区间合并为连续的非重叠区间,避免重叠日期重复计数。
- 第三步:计算每个合并后区间的天数,按学生汇总求和得到最终的总借出天数。
完整SAS实现代码
/* 1. 读取原始借阅数据,转换日期为SAS日期格式并做边界截断 */ data borrow_records; input Student $ Book & $50. Date_Borrowed date9. Date_Returned date9.; format Date_Borrowed Date_Returned yymmdd10.; /* 定义2021年10月的起止边界 */ oct_start = '01OCT2021'd; oct_end = '31OCT2021'd; /* 截断日期到10月范围内 */ adj_borrow = max(Date_Borrowed, oct_start); adj_return = min(Date_Returned, oct_end); /* 过滤完全不在10月的无效记录 */ if adj_borrow <= adj_return; drop oct_start oct_end Book Date_Borrowed Date_Returned; datalines; David A Thousand Splendid Suns 01Oct2021 05Oct2021 David Jane Eyre 09Oct2021 13Oct2021 David Please Look After Mom 21Oct2021 29Oct2021 Fiona Sense and Sensibility 05Oct2021 14Oct2021 Fiona The Girl Who Saved the King of Sweden 05Oct2021 14Oct2021 Fiona A Fort of Nine Towers 02Oct2021 17Oct2021 Fiona One Hundred Years of Solitude 20Oct2021 30Oct2021 Fiona The Unbearable Lightness of Being 20Oct2021 30Oct2021 Greg Fahrenheit 451 06Oct2021 11Oct2021 Greg One Hundred Years of Solitude 10Oct2021 17Oct2021 Greg Please Look After Mom 15Oct2021 21Oct2021 Greg 4 3 2 1 20Oct2021 27Oct2021 Greg The Girl Who Saved the King of Sweden 27Oct2021 03Nov2021 Marcus Fahrenheit 451 01Oct2021 04Oct2021 Marcus Nectar in a Sieve 15Oct2021 15Oct2021 Marcus Please Look After Mom 30Oct2021 31Oct2021 Priya Like Water for Chocolate 02Oct2021 21Oct2021 Priya Fahrenheit 451 21Oct2021 22Oct2021 Sasha Baudolino 03Oct2021 29Oct2021 Sasha A Thousand Splendid Suns 07Oct2021 16Oct2021 Sasha A Fort of Nine Towers 26Oct2021 01Nov2021 ; run; /* 2. 按学生+借阅日期排序,为区间合并做准备 */ proc sort data=borrow_records; by Student adj_borrow adj_return; run; /* 3. 合并同一学生的重叠/相邻借阅区间 */ data merged_intervals; set borrow_records; by Student; retain current_start current_end; /* 每个学生的第一条记录初始化区间边界 */ if first.Student then do; current_start = adj_borrow; current_end = adj_return; end; else do; /* 当前区间和已存储区间重叠/相邻,更新区间结束边界 */ if adj_borrow <= current_end + 1 then do; current_end = max(current_end, adj_return); end; /* 区间不重叠,输出上一个完整区间,初始化新的区间 */ else do; output; current_start = adj_borrow; current_end = adj_return; end; end; /* 输出每个学生的最后一个区间 */ if last.Student then output; format current_start current_end yymmdd10.; drop adj_borrow adj_return; run; /* 4. 按学生汇总计算10月有书在借的总天数 */ proc sql; create table borrow_day_result as select Student, sum(current_end - current_start + 1) as borrow_days label="10月有书在借总天数" from merged_intervals group by Student order by Student; quit; /* 打印最终结果 */ proc print data=borrow_day_result noobs label; run;
运行结果
| Student | 10月有书在借总天数 |
|---|---|
| David | 19 |
| Fiona | 27 |
| Greg | 26 |
| Marcus | 7 |
| Priya | 21 |
| Sasha | 29 |
内容的提问来源于stack exchange,提问作者trjcqs
相关产品推荐
相关产品推荐

