在 proc sql 中解析为语句的 SAS 宏

SAS macro to resolve in proc sql into statement

谁能帮我解决这里的语法错误。 Y 是包含一些值的数据集,比如 1,2,3,4(实际上它包含很多记录)

/*This is working fine*/
proc sql;
select count(*) into:m from y;
select x into:a1 - :a4 from y;
quit;
%put &m &a1 &a2 &a3 &a4;

/*When i am trying to create a macro which will have a1 to a4 values, it's giving me error. below is my approach*/

proc sql;
select count(*) into:m from y;
select x into:a1 - :a||trim(left(&m.)) from y;
quit;
%put &m &a1 &a2 &a3 &a4;

请有人帮我解决这个问题,解释一下错误的原因。

你不需要再告诉有多少了。 SQL 将创建足够的变量。

data y;
   do x = 1 to 4;
      output;
      end;
   run;
proc sql;
   select count(*) into:m from y;
   select x into:a1- from y;
   quit;
%put &m &a1 &a2 &a3 &a4;

这至少从 9.3 开始有效。

虽然 DN 在另一个答案中是正确的,您真的不必再为此烦恼了,但我认为向您展示您尝试中的错误很有用 - 这并不是一种不合理的方法。

您不能像以前那样使用 trim。这将对字符表达式进行操作,而不是对程序代码进行操作 - 宏变量正在生成(程序代码)。您有几个选项可以执行此操作。

首先是%trim autocall macro。这就是您直接做您想做的事情的方式。

proc sql;
select count(*) into :ccount trimmed from sashelp.class;
select name into :a1 - :a%trim(&ccount.) from sashelp.class;
quit;
%put &ccount &a1 &a2 &a3 &a4;

其次,SQL 实际上会以两种可能的方式为您执行此操作。

  • trimmed 关键词
  • separated by

trimmed 关键字作为 into 子句的一部分,或者使用 separated by 即使只有一个结果值,也会导致修剪结果(因此,左对齐,后面没有空格或preceding) 存储在目标宏变量中。 (为什么 separated by 的默认值与 not 的默认值不同是 SAS 中与不破坏有效代码相关的奇怪事情之一,即使它是一个愚蠢的结果。)

proc sql;
select count(*) into :ccount trimmed from sashelp.class;
select name into :a1 - :a&ccount. from sashelp.class;
quit;
%put &ccount &a1 &a2 &a3 &a4;

语法错误可能是由于不了解宏处理器的工作原理造成的。它只是一个生成文本的工具。生成的文本需要是有效的 SAS 代码才能执行。所以试着写这样的东西:

into :a1 - :a||trim(left(&m.))

将不起作用。唯一的宏触发器是对 M 宏变量的引用。所以这将评估为:

into :a1 - :a||trim(left(   4))

但是 INTO 运算符只需要那里的宏变量名称列表的上限名称。它无法处理 ||连接运算符或调用函数,如 TRIM() 或 LEFT().

幸运的是,您不需要这些,因为 PROC SQL 的 INTO 子句足够智能,可以只生成您需要的宏变量。如果您使用的是当前版本的 SAS,您可以将上限留空。

into :a1 - 

或者,如果您 运行 使用旧版本,您只需使用大于任何预期观察次数的上限。

into :a1-:a999999

此外,您不需要 运行 查询两次以找出找到的记录数 SQL。它会将计数设置到自动宏变量 SQLOBS 中。所以你的查询变成:

proc sql noprint;
  select x into :a1- from y;
%let m=&sqlobs;
quit;