SAS PROC SQL-使用宏程序返回的值计算列

SAS PROC SQL-使用宏程序返回的值计算列,sas,sas-macro,proc-sql,Sas,Sas Macro,Proc Sql,我想自动化以下日期计算:向给定的数字变量添加(或减除)X个月,该变量表示YYYYMM形式的日期,即201901代表2019年1月。 示例:201901+13个月=202002 以下宏返回所需的值(&id) 我希望在PROC SQL中使用宏,如下所示: PROC SQL; CREATE TABLE want AS SELECT T1.*, %suma_meses(T1.old_date, T1.x_months) AS new_date FROM have T1 WHERE %suma_mese

我想自动化以下日期计算:向给定的数字变量添加(或减除)X个月,该变量表示YYYYMM形式的日期,即201901代表2019年1月。 示例:201901+13个月=202002

以下宏返回所需的值(&id)

我希望在PROC SQL中使用宏,如下所示:

PROC SQL;
CREATE TABLE want AS 
SELECT T1.*, %suma_meses(T1.old_date, T1.x_months) AS new_date
FROM have T1
WHERE %suma_meses(T1.old_date, T1.x_months) > 201801 ;
QUIT;
这能做到吗?
由于这种类型的计算对于我所在领域的人来说是一项非常经常性的任务(我们不是管理员、工程师等),因此我们的想法是与其他用户共享宏以简化语法。换句话说,我们希望使代码更具可读性,避免复制粘贴问题,并将非高级用户从剧烈的计算错误XD中解放出来(特别是当涉及子查询且X为负时)。这样的宏将使我们的生活更轻松。

如果您运行的是相对较新版本的SAS,则应将其作为FCMP函数而不是宏函数共享

proc fcmp
允许您创建(和保存)用户定义的函数,这些函数可以从datasteps和
proc sql
中调用(也可以通过
%sysfunc()
等方式调用)

下面是一个
fcmp
函数的示例,该函数返回两个指定数字之间的随机数:

proc fcmp outlib=work.funcs.funcs;
  function randbetween(min,max);
    return ( min + floor( ( 1 + max - min ) * rand("uniform") ) );
  endsub;
run;        
用法示例:

data example;
 do cnt=1 to 5;
   x = randbetween(1,100);
   output;
 end;
run;
结果:

Obs cnt x
1   1   8
2   2   93
3   3   98
4   4   97
5   5   12

如果SAS对您的功能不认可有任何投诉,您可能需要使用以下内容更新您的选项:
options cmplib=(work.funcs)

听起来您试图将201801之类的数字视为代表2018年的第一个月,然后添加一个月数,并使用相同的“样式”生成一个数字

如果要在宏代码中使用数字字符串,可以创建如下宏:

%macro add_months_macro(date,months);
%sysfunc(intnx(month,%sysfunc(inputn(&date.01,yymmdd8)),&months),yymmn6)
%mend;
但是,如果您想要一种方法,可以在普通SAS语句中使用变量值,那么就根本不用
%sysfunc()
。相反,只需使用宏生成SAS代码即可直接调用函数

%macro add_months_sas(date,months);
input(put(intnx('month',input(cats(&date,'01'),yymmdd8.),&months),yymmn6.),6.)
%mend;
那么您的WHERE子句将如下所示:

WHERE %add_months_sas(T1.old_date, T1.x_months) > 201801 
但是您实际上应该将数字转换为实际日期,然后使用
INTNX()
函数添加月份。
这样就根本不需要宏了

WHERE intnx('month',T1.old_date, T1.x_months) > '01JAN2018'd  

将字符串T1.old_date除以100时,
%EVAL()
应该产生什么值?为此,宏需要从输入数值常量生成实际数字或生成计算数字的SAS代码。从输入变量名。请描述宏试图执行的操作?看起来它可能试图将6位整数视为代表年和月的值。您可能希望将“诡计”扼杀在萌芽状态(或尽可能早地放在数据流中),并将您的自编码日期值(yyyy*100+mm)转换为SAS日期值,以便进行下游处理和分析。SAS日期值适用于日期算术和基于日期的函数,尤其是
INTCK
INTNX
。使用SAS格式显示输出中所需的日期值(mm/yyyy、yyyy-mm、mon-year等)。谢谢Tom!为什么%sysfunc不适用于我的目的?它是否会生成其他内容而不是数字字符串?对于宏处理器而言,旧日期只是一个字符串。宏处理器只是生成文本。它很有用,因为您可以使用它通过生成文本字符串来创建动态程序,这些文本字符串是SAS命令,SAS可以在宏处理器完成其工作后编译和运行。谢谢Robert。此功能在我的SAS版本中正常工作。为了完整起见,我认为有必要指出,SAS将通过
proc fcmp
构建的函数识别为系统函数,即
%put%sysfunc(randbetween(0,1))在日志中写入了一个有效值。@ChuckRamirez我相信这些函数是在一个虚拟的“数据步骤”中执行的。因此,如果我认为它们是数据步进函数。调用
%sysfunc
时,仅限于调用数据步骤可用的函数。。。
WHERE intnx('month',T1.old_date, T1.x_months) > '01JAN2018'd