基于宏变量的 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;
我创建了一个宏变量,它是程序运行少一个月时的日期时间,格式为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;