我创建了一个宏变量,它是程序运行时的日期时间减去一个月,格式化为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,^,^ =,|,||,〜,〜=。
我不知道为什么会抛出这个错误。我做错了什么?
谢谢!
答案 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;