【问题标题】:Defining Fixed SAS Macro Variables定义固定 SAS 宏变量
【发布时间】:2019-04-05 03:06:53
【问题描述】:

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

我想知道的第二件事是我是否可以通过 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;

【问题讨论】:

标签: macros sas


【解决方案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 将能够识别宏名称的结束位置。有些人总是包含它,除非需要,否则我个人将其省略。

【讨论】:

    【解决方案2】:

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

    • UNION ALLSQL
    • 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 过程为您排列列。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-02
      • 2021-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多