PROC SQL" SELECT INTO"不创建宏变量

时间:2018-05-21 17:31:38

标签: sas sas-macro

我遇到了使用proc sql select into :逻辑创建宏变量的问题。代码似乎非常简单,但我应该注意,导致问题的宏是从其他几个宏调用的。

以下是导致问题的代码段。

%do year_num=1 %to 5;
    %if &year_num=1 %then %let min_date = %eval(&max2.-17);
    %else %let min_date = %eval(&min_date.-12);

    data tmp;
    set bf(firstobs=&min_date obs=%eval(11+&min_date));
    run;

    data tmp2;
    set bf(firstobs=%eval(5+&min_date) obs=%eval(7+&min_date));
    run;

    proc sql noprint;
    select sum(EP), sum(ExpectedLoss)
      into :totep, :totexpt
    from tmp;

    select sum(EP), sum(ExpectedLoss)
      into :partep, :partexpt
    from tmp2;
    quit;

    %put _LOCAL_;

    *Other code...;

%end;

出于某种原因,变量toteptotexptparteppqrtexpt未创建,我无法在日志中找到任何有用的信息这可能会对情况有所了解。

以下是日志的一部分,包括_LOCAL_的输出。

SYMBOLGEN:  Macro variable YEAR_NUM resolves to 1
SYMBOLGEN:  Macro variable MAX2 resolves to 96
MPRINT(BFMETHOD):   data tmp;
SYMBOLGEN:  Macro variable MIN_DATE resolves to 79
SYMBOLGEN:  Macro variable MIN_DATE resolves to 79
MPRINT(BFMETHOD):   set bf(firstobs=79 obs=90);
MPRINT(BFMETHOD):   run;
MPRINT(BFMETHOD):   data tmp2;
SYMBOLGEN:  Macro variable MIN_DATE resolves to 79
SYMBOLGEN:  Macro variable MIN_DATE resolves to 79
MPRINT(BFMETHOD):   set bf(firstobs=84 obs=86);
MPRINT(BFMETHOD):   run;
MPRINT(BFMETHOD):   proc sql noprint;
MPRINT(BFMETHOD):   select sum(EP), sum(ExpectedLoss) into :totep, :totexpt from tmp;
MPRINT(BFMETHOD):   select sum(EP), sum(ExpectedLoss) into :partep, :partexpt from tmp2;
MPRINT(BFMETHOD):   quit;
BFMETHOD I 12
BFMETHOD DSET all
BFMETHOD SEAS_MIN 0.6
BFMETHOD YEAR_NUM 1
BFMETHOD SEAS_MAX 1.66666666666666
BFMETHOD MIN_DATE 79

data tmp;     set bf(firstobs=79 obs=90);     run;

NOTE: There were 12 observations read from the data set WORK.BF.
NOTE: The data set WORK.TMP has 12 observations and 35 variables.
NOTE: Compressing data set WORK.TMP increased size by 100.00 percent.
      Compressed is 2 pages; un-compressed would require 1 pages.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

109       +    data tmp2;     set bf(firstobs=84 obs=86);     run;

NOTE: There were 3 observations read from the data set WORK.BF.
NOTE: The data set WORK.TMP2 has 3 observations and 35 variables.
NOTE: Compressing data set WORK.TMP2 increased size by 100.00 percent.
      Compressed is 2 pages; un-compressed would require 1 pages.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds


109       +                                                             proc sql noprint;
109       +                                                                                   select sum(EP), sum(ExpectedLoss)       into :totep, :totexpt     from tmp;
109       +
     select sum(EP), sum(ExpectedLoss)       into :partep, :partexpt     from tmp2;
109       +
     quit;
NOTE: PROCEDURE SQL used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds

如果我从noprint语句中删除proc sql,则会输出正确的值,因此我不确定发生了什么。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

您的问题几乎肯定与执行时间有关。特别是在使用call execute时,您很容易遇到SAS处理器解决宏变量的时间问题,而不是给定有用的值。

这是一个简化的例子。我专门创建了一个数据集,以便您可以看到何时发生(这不是必要的步骤,也不会影响示例,它只是创建一个有用的日志条目)。

请注意,当宏运行时,一切都按照您的预期运行;但是当它与call execute一起运行时,%put执行之前宏实际执行。

第三个示例使用%nrstr强制SAS在实际运行宏之前不尝试解析宏 - 这会导致正确提交宏。

实际上,第一个call execute版本有SAS处理宏文本,然后将其提交给sas.exe - 这是你真的不想要的。添加%nrstr修复了。

%macro do_something();
    %local mlist;
    data class_m;
      set sashelp.class;
      where sex='M';
    run;

    proc sql;
      select name into :mlist separated by ' '
      from class_m;
    quit;

    %put &=mlist;
%mend do_something;

%put Macro run on its own;
%do_something;


%put Macro run via call execute;
options mprint symbolgen;
data _null_;
  set sashelp.class;
  if _n_=1 then call execute('%do_something()');
  stop;
run;

%put Macro run with nrstr and call execute;
data _null_;
  set sashelp.class;
  if _n_=1 then call execute('%nrstr(%do_something())');
  stop;
run;