Date 基于宏变量的SAS子集设置

Date 基于宏变量的SAS子集设置,date,sas,sas-macro,Date,Sas,Sas Macro,我创建了一个宏变量,它是程序运行不到一个月时的datetime,格式为datetime20: %let startDate = %sysfunc(intnx(dtmonth, %sysfunc(datetime()), -1), datetime20.); 这部分工作正常(如果我现在运行它,它将返回01JUL2015:00:00:00),但我要做的是在PROC SQL语句中基于此日期对数据集进行子集。基本上,我想保留所有发生在最后一个月的日期。我的代码是: proc sql; create t

我创建了一个宏变量,它是程序运行不到一个月时的datetime,格式为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”类型,但仍会引发错误:

错误22-322:语法错误,应为以下之一:;,!,!!,&,*,***,+,-,/,=,和,EQ,EQT,EXCEPT,GE,GET,GROUP,GT,GTT,HAVING,INTERSECT, LE,LET,LT,LTT,NE,NET,NOT,OR,ORDER,OUTER,UNION,^,^,^=,| |,~,~=

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


谢谢

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

proc sql;
create table work.last_month as
select * from work.existing_table
where date >= 01JUL2015:00:00:00;
quit;
这不是有效的SAS代码。 您可以使用SAS datetime编号,而不是将其转换/格式化为datetime值,也可以创建一个用于比较的日期文字。 要创建日期文字,请将宏变量括在引号中,并以dt结尾以指示日期时间值

proc sql;
create table work.last_month as
select * from work.existing_table
where date >= "01JUL2015:00:00:00"dt;
quit;
要创建SAS日期时间数值,请删除%sysfunc()中的格式


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

proc sql;
create table work.last_month as
select * from work.existing_table
where date >= 01JUL2015:00:00:00;
quit;
这不是有效的SAS代码。 您可以使用SAS datetime编号,而不是将其转换/格式化为datetime值,也可以创建一个用于比较的日期文字。 要创建日期文字,请将宏变量括在引号中,并以dt结尾以指示日期时间值

proc sql;
create table work.last_month as
select * from work.existing_table
where date >= "01JUL2015:00:00:00"dt;
quit;
要创建SAS日期时间数值,请删除%sysfunc()中的格式


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

因此:

这是非法的,因为这不是一个日期时间值,它是一个很好的可读日期时间,SQL/SAS看着它,却不知道如何处理它

您可以从
%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;

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

因此:

这是非法的,因为这不是一个日期时间值,它是一个很好的可读日期时间,SQL/SAS看着它,却不知道如何处理它

您可以从
%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;

谢谢答案非常相似,在这种情况下,协议是什么?@Reeza其实并不重要,我可以删除我的,或者干脆留下。我通常认为,如果我的解释更符合某人的口味,那么留下它不会有什么坏处。即使这两种方法都有效,我还是倾向于从sysfunc中删除格式。使用原始datetime值比使用文字更容易,特别是如果在程序中稍后对值进行进一步操作的话。很好,你提到了两种选择。谢谢。答案非常相似,在这种情况下,协议是什么?@Reeza其实并不重要,我可以删除我的,或者干脆留下。我通常认为,如果我的解释更符合某人的口味,那么留下它不会有什么坏处。即使这两种方法都有效,我还是倾向于从sysfunc中删除格式。使用原始datetime值比使用文字更容易,特别是如果在程序中稍后对值进行进一步操作的话。很好,你提到了两种选择。