基于宏变量的 SAS 子集化

SAS subsetting based on a macro variable

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

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

这部分工作正常(如果我现在 运行 它,它 returns 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:语法错误,应为以下之一:;、!、!!、&、*、**、+、-、/、<、<=、 <>, =, >, >=, AND, EQ, EQT, EXCEPT, GE, GET, GROUP, GT, GTT, HAVING, 相交, 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 日期时间数字而不是 convert/format 用于日期时间值,或者创建日期文字以进行比较。 要创建日期文字,请将宏变量括在引号中并以 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;

您的问题是您正在格式化结果 - 不要那样做。请记住,宏变量只是创建文本,它们不是实际变量——它们没有像 "formats" 这样的概念(其中常规 SAS 变量可以是数字日期值和 "pretty" 格式文本)。

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 看着但不知道如何处理。

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