基于宏变量的SAS子集

时间:2015-08-04 18:58:30

标签: date sas sas-macro

我创建了一个宏变量,它是程序运行时的日期时间减去一个月,格式化为datetime20:

%let startDate = %sysfunc(intnx(dtmonth, %sysfunc(datetime()), -1), datetime20.);

这部分工作正常(如果我现在运行它,它返回01JUL2015:00:00:00),但我想要做的是在PROC SQL语句中基于此日期对数据集进行子集化。基本上我想保留上个月发生日期的所有内容。我的代码是:

proc sql;
create table work.last_month as
select * from work.existing_table
where date >= &startDate.;
quit;

列“date”和变量“startDate”都是'datetime20'类型,但仍然会抛出错误:

ERROR 22-322:语法错误,期望以下之一:;,!,!!,&,*,**,+, - ,/,<,< =,               <&gt ;, =,>,> =,AND,EQ,EQT,EXCEPT,GE,GET,GROUP,GT,GTT,HAVING,INTERSECT,               LE,LET,LT,LTT,NE,NET,NOT,OR,ORDER,OUTER,UNION,^,^ =,|,||,〜,〜=。

我不知道为什么会抛出这个错误。我做错了什么?

谢谢!

2 个答案:

答案 0 :(得分:4)

宏处理器是代码生成器,因此您的代码正在生成

proc sql;
create table work.last_month as
select * from work.existing_table
where date >= 01JUL2015:00:00:00;
quit;

这不是有效的SAS代码。 您可以使用SAS日期时间编号,而不是将其转换/格式化为日期时间值,或创建日期文字以进行比较。 要创建日期文字,请将宏变量括在引号中,并以dt结束以指示日期时间值。

proc sql;
create table work.last_month as
select * from work.existing_table
where date >= "01JUL2015:00:00:00"dt;
quit;

要创建SAS日期时间数值,请删除%sysfunc()中的格式。

%let startDate = %sysfunc(intnx(dtmonth, %sysfunc(datetime()), -1));

proc sql;
create table work.last_month as
select * from work.existing_table
where date >= &startDate.;
quit;

答案 1 :(得分:1)

您的问题是您正在格式化结果 - 不要这样做。请记住,宏变量只是创建文本,它们不是实际变量 - 它们不具有类似"格式"等概念。 (常规SAS变量可以是数字日期值和"漂亮的#34;格式化文本)。

1    %let startDate = %sysfunc(intnx(dtmonth, %sysfunc(datetime()), -1), datetime20.);
2    %put &=startdate.;
STARTDATE=01JUL2015:00:00:00

所以:

proc sql;
create table work.last_month as
select * from work.existing_table
where date >= 01JUL2015:00:00:00;
quit;

这是非法的,因为它不是日期时间值,它是一个很好的人类可读的日期时间,SQL / SAS看起来并且不知道如何处理。< / p>

您可以从%sysfunc中删除格式位,或在其周围添加"..."dt以使其成为日期时间常量。

data existing_table;
  do date=datetime()-86400*50 to datetime() by 86400;
    output;
  end;
run;

proc sql;
create table work.last_month as
select * from work.existing_table
where date >= "&startdate."dt;
quit;