PROC SQL "SELECT INTO" не создает макропеременную - PullRequest
0 голосов
/ 21 мая 2018

Я столкнулся с проблемой создания макропеременных с использованием логики 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;

По какой-то причине переменные totep, totexpt, partep и pqrtexpt не создаются, и я не могу найти в журнале никакой полезной информации, которая могла бы пролить свет на ситуацию.

Вот часть журнала, включая вывод _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 голосов
/ 21 мая 2018

Ваша проблема почти наверняка связана со сроками исполнения.В частности, при использовании 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;
...