繁体   English   中英

SAS中带有PROC SQL的函数样式宏?

[英]function style macro in SAS with PROC SQL?

是否可以使这种形式的宏起作用?

    %macro tableMath(input1,input2);
    %local result;
    proc sql; ---some code here using inputs--- quit;
    proc sql; ---more code here--- quit;
    proc sql;
    select something into: result
    quit;
    &result
    %mend;

我想对数据集的每次观察运行一些相当复杂的逻辑,并且在执行此操作之前,我使用的任何其他语言都是将其封装在一个函数中,该函数每次调用都会返回结果-我我不确定如何在SAS中执行此逻辑。

编辑:input1和input2将是数据集的列,结果将用于在程序另一部分的其他宏中创建新列。 我不需要特定的代码解决方案,我只是不了解如何在SAS中需要返回值的情况下执行传统的函数逻辑...

正如Richard所写的那样,函数样式的宏会发出SAS代码。 开发函数样式宏的一般规则是它们仅包含宏语言语句。 它们包含的任何SAS代码都会被发出。 从历史上看,这使得编写函数式宏非常困难/烦恼,该宏将像处理DATA步骤一样处理数据。 幸运的是,SAS添加了一个函数DOSUBL ,该函数使编写在“侧边会话”中执行SAS代码并发出结果的函数式宏更加容易。 请参阅Rick Langston的论文

这是一个函数样式宏的示例,该宏使用DOSUBL对表中的记录数进行计数,并发出该计数。 (这是获得记录计数的一种非常低效的方法,仅是在SQL中执行操作的示例)。

%macro SQLcount(table);
  %local rc emit; 

  %let rc=%sysfunc(dosubl(%nrstr(
     proc sql noprint;
      select count(*) into :emit trimmed
      from &table
     quit;
  )));

  &emit 
%mend ;

可以像这样使用:

proc sql ;
  select name
        ,%SQLcount(sashelp.shoes) as ShoeCount  /*emits 395*/
  from sashelp.class
  ;
quit ;

运行上述步骤时,它将从sashelp.class返回19行名称,并且ShoeCount的值将为每行395。 请注意,宏SQLcount仅执行一次。 在编译/解释PROC SQL步骤时,将看到对SQLcount的调用,并执行了该宏并发出395。该步骤变为:

proc sql ;
  select name
        ,395 as ShoeCount  /*emits 395*/
  from sashelp.class
  ;
quit ;

DOSUBL使用“辅助会话”执行代码,这使您可以在辅助会话中执行PROC SQL步骤,而主会话正在解释PROC SQL步骤。

从您的问题中我无法确定您是否想要这种用例。 您可能需要一个函数样式的宏,您可以在其中从表中将值传递给它,并使该宏在每个值上执行并返回某些内容。 假设您有一个表,该表是一个表名列表,并且想要使用SQL获取每个表中的记录数:

data mytables ;
  input table $20. ;
  cards ;
sashelp.shoes
sashelp.class
sashelp.prdsale
;
quit ;

您可以通过使用resolve()函数从数据构建宏调用,将宏的执行延迟到SELECT语句执行之前来完成:

proc sql ;
  select table
        ,resolve('%SQLcount('||table||')') as count
  from mytables
  ;
quit ;

这样,SQLcount将被调用三次,并将返回每个数据集中的记录数。

table                 count
---------------------------
sashelp.shoes         395
sashelp.class         19
sashelp.prdsale       1440

解释PROC SQL步骤时看不到宏调用,因为该宏调用被单引号隐藏。 然后,在SELECT语句执行时,resolve函数调用宏,将table的值作为参数值传递,并且该宏发出记录计数。 这类似于使用数据来驱动宏调用的CALL EXECUTE方法。

您声明要:

对数据集的每次观察运行一些相当复杂的逻辑

为此,您应该使用SAS语言而不是宏处理器或PROC SQL。 您可以使用数据步骤。 或者,对于更复杂的逻辑,您应该查看PROC DS2。

听起来您可能想使用proc fcmp创建proc fcmp函数。 这基本上是一种创建自己的SAS函数的方法,该函数可在proc sqldata步骤中使用。 例如:

/******************************************************************************
** PROGRAM:  COMMON.FCMP_DIV.SAS
**
** DESCRIPTION: PERFORMS A MATHEMATICAL DIVISION BUT WILL RETURN NULL IF THE
**              NUMERATOR OR DENOMINATOR IS MISSING (OR IF THE DIVISOR IS 0).
**
******************************************************************************/

proc fcmp outlib=common.funcs.funcs;

  function div(numerator, denominator);

    if numerator eq . or denominator in (0,.) then do;
      return(.);
    end;
    else do;
      return(numerator / denominator);
    end;

  endsub;
run;

用法示例(示例是数据步骤,但在SQL中同样有效):

data x;
  x1  = div(1,0);
  x2  = div(1,.);
  x3  = div(1,1);

  x4  = div(0,0);
  x5  = div(0,.);
  x6  = div(0,1);

  x7  = div(.,0);
  x8  = div(.,.);
  x9  = div(.,1);

  put _all_;
run;

宏函数不返回值。 宏函数可以“发出”源代码,

  • 是一个或多个步骤,
  • 这是将代码合并到语句中的摘要,
  • 这是一个或多个步骤的一部分,
  • 等等

对于要在SQL中“执行”操作的情况,可以编写SQL视图 ,然后

  • %sysfunc(open())
  • 用...处理
    • %sysfunc(set())
    • %sysfunc(getvarn())
    • %sysfunc(getvarc())

并非所有的SQL功能都可以通过这种技术使用-在select something into :result必须是带有select something的视图,并且宏将使用getvarc读取结果。

以open / set / get方式进行的访问不会引起步骤边界的发生,因此宏处理可以按照其逻辑进行,并最终发出源代码以供摘要使用。 (使用者是处理宏代码,隐式编译和运行SAS步骤的SAS执行程序)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM