Создайте несколько списков макропеременных SAS из одного набора данных - PullRequest
0 голосов
/ 12 октября 2018

Поскольку длина значения макропеременной не может превышать максимальную длину (65534), я не могу создать одну макропеременную для всех моих наблюдений.Я хотел бы создать макрос для итерации моего набора данных, чтобы сгенерировать несколько числовых списков, которые я могу передать оператору where в proc sql.

Вместо этого:

*proc sql noprint;
    select ID into :ParaList separated by ','
    from work.ID_LIST(**firstobs=1 obs=5000**);
quit;*

*proc sql noprint;
    select ID into :ParaList2 separated by ','
    from work.ID_LIST(**firstobs=5001 obs=10000**);
quit;*

*proc sql noprint;
    select ID into :ParaList3 separated by ','
    from work.ID_LIST(**firstobs=10001 obs=15000**);
quit;*

*proc sql noprint;
    select ID into :ParaList4 separated by ','
    from work.ID_LIST(**firstobs=15001 obs=20000**);
quit;*

Я бы хотел что-то вроде:

*proc sql noprint;
    select ID into :List1-Last4 separated by ','
    from work.ID_LIST(**firstobs=1 obs=&LASTOBS** BY 5000);
quit;*

Я хотел бы создать макрос для цикла через каждые 5000 наблюдений илитак что до последнего наблюдения я могу перейти в инструкцию where, например, где id в (& ParaList, & ParaList2, & ParaList3, & ParaList4).Я знаю, что есть альтернативы, такие как

id in (select id from work.table)

, но в этом случае это не работает.Я опрашиваю Hadoop через SAS и не имел никакого успеха, кроме передачи списков макропеременных.

Ответы [ 4 ]

0 голосов
/ 12 октября 2018

Мне нравится решение @Richard, оно сделает его более чистым и эффективным.Вы также можете попробовать неявный проход, если ваш набор данных не очень большой.

 Libname SASTAB "yoursaslocation";
 Libname HTAB  your hadoop parameters;

 proc sql;
 create HTAB.newtable as 
 select * froom HTAB.yourtable
 where id in (Select id from SASTAB.yoursastable);
0 голосов
/ 12 октября 2018

Вы можете легко использовать шаг данных для генерации макропеременных.Вы также должны сгенерировать макропеременную, которая вызывает все остальные макропеременные.

%let n_per_list=5 ;
data _null_;
  length idlist $32000;
  length macrolist $1000 ;
  retain macrolist;
  do i=1 to &n_per_list until (eof);
    set id_list end=eof;
    idlist=catx(',',idlist,id);
  end;
  listno+1;
  call symputx(cats('paralist',listno),idlist);
  macrolist=catx(',',macrolist,cats('&','paralist',listno));
  call symputx('paralist',macrolist);
run;

, которая для простого теста 20 значений, разбитых на группы по 5, дает такой результат:

151  %put Paralist=%superq(ParaList);
Paralist=&paralist1,&paralist2,&paralist3,&paralist4
152  %put &=Paralist1;
PARALIST1=1,2,3,4,5
153  %put &=Paralist;
PARALIST=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20

Или вы можете просто посмотреть на генерацию кода в макросе вместо использования макропеременных.Это не должно иметь никаких ограничений на длину списка, который вы можете создать.Вы можете попытаться выяснить, как открыть набор данных внутри макроса, не генерируя никакого кода SAS, чтобы результат вызова макроса был просто списком значений.Но было бы намного проще сгенерировать исходный код для определения макроса в файл, а затем% включить файл для его определения.

filename code temp;
data _null_;
  set id_list end=eof;
  file code lrecl=80;
  if _n_=1 then put '%macro paralist;' ;
  else put ',' @ ;
  put id @ ;
  if eof then put / '%mend paralist;' ;
run;

Результат для того же тривиального списка значений 20.

163  %include code / source2;
NOTE: %INCLUDE (level 1) file CODE is file /.../#LN00043.
164 +%macro paralist;
165 +1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 ,19 ,20
166 +%mend paralist;
NOTE: %INCLUDE (level 1) ending.
167  %put %paralist;
1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 ,19 ,20
0 голосов
/ 12 октября 2018

Можете ли вы создавать временные таблицы в Hadoop?Загрузите данные ID_LIST во временную таблицу, а затем используйте их в сквозном запросе.

libname hdp      hadoop noprompt="… connection parameters …";
libname hdp_temp hadoop noprompt="… connection parameters …" dbmstemp=yes;

proc delete data=hdp_temp.id_list;run;
data hdp_temp.id_list;
  set work.my_id_list;
run;

* im not sure on the Hadoop side object naming patterns and default schemas, 
* so this code shows dbo. as is the case in SQL Server;
* SAS libname option dmbstemp=yes for SQL Server causes created tables to be
* referenced as dbo.##<tablename>;

proc sql;
  connect using hadoop;
  create table work.susbset_of_big as
  select * from connection to Hadoop
  ( select * from dbo.my_big_remote_table
    where id in (select id from dbo.##id_list)
  );
quit;
0 голосов
/ 12 октября 2018

Вы можете сделать это с помощью data step do петли и call execute().

data _null_;
set lib.id_list (nobs=totobs);

do i = 1 to totobs by 5000;

call execute(cat(
    'proc sql;
     select ID into :paralist', i,' separated by ','
     from lib.id_list (firstobs=', i,
    ' obs=5000); quit;'
    ));

call execute(cats('%put |paralist',i,'|;'));

end;
run;

Подробнее о execute вызове функции в data step REF1 REF2

Приведенный выше вызов создает строку

proc sql;
select id into:paralist1 separated by ','
from lib.id_list (firstobs=1 obs=5000);
quit;

proc sql;
select id into:paralist5001 separated by ','
from lib.id_list (firstobs=5001 obs=5000);
quit;

/* etc */
...