定义固定的SAS宏变量

时间:2018-10-31 21:09:53

标签: macros sas

我正在尝试运行宏,但是由于一段时间没有与数据库的连接,我不确定它是否会解决。我想知道宏是否正确编写,并且会在每次通过代码时解析状态(即重复执行并为每个状态创建一个表)。

我想知道的第二件事是我是否可以通过from语句运行宏。例如,让entpr为我要从中提取的数据库。以下内容能否正确解决:

    proc sql;
    select * from entpr.&state.; /*Do I need the . after &state?*/

其余的代码:

    libname mdt "........."
    %let state = ny il ar ak mi;

    proc sql;
    create table mdt.&state._members
    as select
corp_ent_cd
,mkt_sgmt_admnstn_cd
,fincl_arngmt_cd
,aca_ind
,prod_type
,cvyr
,cvmo
,sum(1) as mbr_cnt
from mbrship1_&state.
group by 1,2,3,4,5,6,7;
quit;

2 个答案:

答案 0 :(得分:1)

如果&state包含ny il ar ak mi,则在编写时,代码中的from语句将解析为:from mbrship1_ny il ar ak mi-这是无效的SQL语法。

我的猜测是您要为以下每个表运行SQL语句:

mbrship1_ny 
mbrship1_il 
mbrship1_ar 
mbrship1_ak 
mbrship1_mi

在这种情况下,最简单的宏如下所示:

%macro do_sql(state=);
  proc sql;
    create table mdt.&state._members
    as select
    ... 
    from mbrship1_&state
    group by 1,2,3,4,5,6,7;
  quit;
%mend;
%do_sql(state=ny);
%do_sql(state=il);
%do_sql(state=ar);
%do_sql(state=ak);
%do_sql(state=mi);

关于您是否要包含.的问题,规则是,如果宏变量后面的字符不是a-Z,0-9或下划线,则句点是可选的。这些字符是宏变量名称的有效字符列表,因此只要它不是您不需要的字符之一,因为SAS就能识别宏名称的结尾位置。某些人总是将其包括在内,除非需要,我个人将其保留。

答案 1 :(得分:0)

从多个表中选择数据时,这些表的名称本身包含一些数据(在您的情况下为状态),您可以使用以下方法堆叠数据:

  • UNION ALL中的{li> SQL
  • SET在“数据”步骤

只要要堆叠数据,还应该在查询选择中添加新列以跟踪状态。

考虑此模式以在SQL中堆叠

data one;
do index = 1 to 10; do _n_ = 1 to 2; output; end; end;
run;
data two;
do index = 101 to 110; do _n_ = 1 to 2; output; end; end;
run;

proc sql;
  create table want as
  select 
    source, index
  from 
    (select 'one' as source, * from one)
    union all 
    (select 'two' as source, * from two)
  ;

该模式可以抽象到将由宏生成的SQL源代码模板中。

%macro my_ultimate_selector (out=, inlib=, prefix= states=);
  %local index n state;
  %let n = %sysfunc(countw(&states));

  proc sql;
    create table &out as
    select 
      state
      , corp_ent_cd
      , mkt_sgmt_admnstn_cd
      , fincl_arngmt_cd
      , aca_ind
      , prod_type
      , cvyr
      , cvmo
      , count(*) as state_7dim_level_cnt
    from

      %* ----- use the UNION ALL pattern for stacking data -----;

      %do index = 1 %to &n;
        %let state = %scan(&states, &index);

        %if &index > 1 %then %str(UNION ALL);

        (select "&state" as state, * from &inlib..&prefix.&state.)

      %end;

    group by 1,2,3,4,5,6,7,8  %* this seems to be to much grouping ?;
    ;
  quit;
%mend;

%my_ultimate_selector (out=work.want, inlib=mdt, prefix=mbrship1_, states=ny il ar ak mi)

如果inlib表中的列在列顺序和类型方面不相同,请使用UNION ALL CORRESPONDING使SQL过程为您排列这些列。