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

SAS中带有PROC SQL的函数样式宏?,sql,sas,sas-macro,Sql,Sas,Sas Macro,是否可以使此窗体的宏正常工作 %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;

是否可以使此窗体的宏正常工作

    %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中需要返回值的传统函数逻辑应该如何执行…

您表示希望:

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

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

您声明要:

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


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

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

  • 这是一个或多个步骤
  • 这是一个代码片段,可以合并到语句中
  • 这是一个步骤中的一个或多个语句
对于希望在SQL中“执行”操作的情况,您可以编写SQL视图,然后

  • 使用
    %sysfunc(open())
    打开
  • 处理
    • %sysfunc(set())
    • %sysfunc(getvarn())
    • %sysfunc(getvarc())
并非所有的SQL功能都能被这种技术利用,
select-something:result
,必须是一个带有
select-something
的视图,宏将
getvarc
读取结果


以open/set/get方式完成的访问不会导致出现步骤边界,因此宏处理可以继续执行其逻辑,并最终发出源代码供代码段级使用。(使用者是处理宏代码并隐式编译和运行SAS步骤的SAS执行器)

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

  • 这是一个或多个步骤
  • 这是一个代码片段,可以合并到语句中
  • 这是一个步骤中的一个或多个语句
对于希望在SQL中“执行”操作的情况,您可以编写SQL视图,然后

  • 使用
    %sysfunc(open())
    打开
  • 处理
    • %sysfunc(set())
    • %sysfunc(getvarn())
    • %sysfunc(getvarc())
并非所有的SQL功能都能被这种技术利用,
select-something:result
,必须是一个带有
select-something
的视图,宏将
getvarc
读取结果


以open/set/get方式完成的访问不会导致出现步骤边界,因此宏处理可以继续执行其逻辑,并最终发出源代码供代码段级使用。(使用者是处理宏代码并隐式编译和运行SAS步骤的SAS执行器)

正如Richard所写,函数式宏发出SAS代码。开发函数式宏的一般规则是,它们只包含宏语言语句。它们包含的任何SAS代码都将被发出。从历史上看,这使得编写一个函数式宏很难/很烦人,该宏将像处理数据步骤一样处理数据。幸运的是,SAS添加了一个函数,DOSUBL,这使得编写函数风格的宏更容易,这些宏在“侧会话”中执行SAS代码并发出结果。看

下面是一个函数样式宏的示例,该宏使用DOSUBL计算表中的记录数,并发出计数。(这是一种非常低效的获取记录计数的方法,只是在SQL中执行某些操作的一个示例)

它可以像这样使用:

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使用“side session”来执行代码,这允许您在side session中执行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
的值作为参数值传递,宏将发出记录计数。这类似于使用数据驱动宏调用的调用执行方法。

正如Richard所写,函数式宏发出SAS代码。T
table                 count
---------------------------
sashelp.shoes         395
sashelp.class         19
sashelp.prdsale       1440
/******************************************************************************
** 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;
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;