【问题标题】:Using the same condition for multiple datasets对多个数据集使用相同的条件
【发布时间】:2020-12-25 18:27:35
【问题描述】:

我的代码如下:

%macro xx(date);
proc sql;
create table test_&date as
select a.*
from population_&date as a
left join new_acct_no as b on a.names = b.names and put(intnx('month',input(put(&date,8. -l),yymmn6.),0,'e'),yymmdd10.) between b.birthdate and b.marriage_dt
left join old_acct_no as c on a.names = c.names and put(intnx('month',input(put(&date,8. -l),yymmn6.),0,'e'),yymmdd10.) between c.birthdate and c.marriage_dt
; 
quit;
%mend;
%date(201812);

我想通过替换“put(intnx('month',input(put(&date,8. -l),yymmn6.),0,'e'),yymmdd10.)”使我的代码更简洁。

任何想法如何做到这一点?

【问题讨论】:

  • BIRTHDATE 和 MARRIAGE_DT 是什么类型的变量?您的代码正在处理它们具有字符串。
  • 你确定逻辑是对的吗?如果 MARRIAGE_DT 是 15DEC2018 怎么办?那是在 2018 年 12 月,但不会受到打击,因为它是在月底之前
  • @tom 是的,我将日期视为字符。 2018-12-31 在生日和结婚日期之间。

标签: loops sas conditional-statements case sas-macro


【解决方案1】:

将静态计算的结果放在Proc SQL 之前的新符号中。 此外,在调用它时使用正确的宏名称。您定义了xx 并正在调用date

例子:

%macro Population_For(date);

%local this_month next_month;

%let this_month = %sysfunc(inputn(&date,yymmn6.));
%let next_month = %sysfunc(intnx(month,&this_month,1));

%put NOTE: SAS Date values &=this_month &=next_month;

proc sql check;
create table test_&date as
select a.*
from population_&date as a
left join new_acct_no as b on a.names = b.names and &next_month between b.birthdate and b.marriage_dt
left join old_acct_no as c on a.names = c.names and &next_month between c.birthdate and c.marriage_dt
; 
quit;
%mend;

%Population_For(201812);

正确的编码还取决于日期值如何存储在表new_acct_noold_acct_no 中。他们是

  • SAS 日期值
  • 构造数字yyyymmdd(即编码年 * 10000 + 月 * 100 + 日)
  • 构造字符串 yyyymmddyyyy-mm-dd

注意:由 SAS 格式 yymmdd10. 呈现的日期表示 yyyy-mm-ddother 数据库系统查询中被解释为日期文字,而在 SAS 中则不然.

日期数据存储为构造字符串yyyy-mm-dd

经过适当审查的 YMD 字符串的字典顺序与它们所代表的 SAS 日期值的顺序相同。

因此,如果两个表都将日期存储为 YMD 字符串,则此类日期数据可以通过计算和使用静态 next_month ymd 表示来处理。此类编码将无需在查询期间将字段birthdatemarriage_dt 中的日期数据转换为SAS 日期。

%local this_month next_month next_YMD;

%let this_month = %sysfunc(inputn(&date,yymmn6.));
%let next_month = %sysfunc(intnx(month,&this_month,1));
%let next_YMD   = %sysfunc(putn(&next_month, yymmdd10.));

%put NOTE: SAS Date values &=this_month &=next_month;

proc sql check;
create table test_&date as
select a.*
from population_&date as a
left join new_acct_no as b on a.names = b.names and &next_month between b.birthdate and b.marriage_dt
left join old_acct_no as c on a.names = c.names and &next_month between c.birthdate and c.marriage_dt
; 

【讨论】:

  • 注意到宏错误!.. 所以在 %sysfunc 下它不能识别字符中的 yyyy-mm-dd 日期?因为变量birthdate和marriage_dt都是字符串格式。
  • 正确,SAS 日期值是从纪元 01JAN1960 开始的天数。所有其他日期表示都希望转换为相应的 SAS 日期值。某些假定yyyymmdd的字符串表示和日期编码在某种程度上适合直接相等比较器和运算符,例如between,但可能包含以下表示或编码与实际日期不一致。
猜你喜欢
  • 2022-08-18
  • 2014-11-14
  • 2018-03-08
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2016-05-14
  • 1970-01-01
  • 2019-09-11
相关资源
最近更新 更多