Отличный вопрос ... У нас есть макрос, который мы используем здесь, чтобы обойти эту проблему, поскольку у нас нет возможности загружать файлы на сервер ODBC или создавать временные таблицы и т. Д. ... Простой пример использования макрос это:
proc sql noprint;
create table xx as
select *
from sashelp.class
where name in ( %ds2list(iDs=sashelp.class, iField=name, iQuote=1, iDelimiter=%str(,)) )
;
quit;
Хотя в приведенном выше примере не используется проход ODBC, с ним все будет в порядке. И если OPTION MPRINT
включен, то журнал покажет что-то вроде следующего:
121 proc sql noprint;
122 create table xx as
123 select *
124 from sashelp.class
125 where name in (%ds2list(iDs=sashelp.class,iField=name,iQuote=1, iDelimiter=%str(,)))
MPRINT(DS2LIST): 'Alfred'
MPRINT(DS2LIST): ,'Alice'
MPRINT(DS2LIST): ,'Barbara'
MPRINT(DS2LIST): ,'Carol'
MPRINT(DS2LIST): ,'Henry'
MPRINT(DS2LIST): ,'James'
MPRINT(DS2LIST): ,'Jane'
MPRINT(DS2LIST): ,'Janet'
MPRINT(DS2LIST): ,'Jeffrey'
MPRINT(DS2LIST): ,'John'
MPRINT(DS2LIST): ,'Joyce'
MPRINT(DS2LIST): ,'Judy'
MPRINT(DS2LIST): ,'Louise'
MPRINT(DS2LIST): ,'Mary'
MPRINT(DS2LIST): ,'Philip'
MPRINT(DS2LIST): ,'Robert'
MPRINT(DS2LIST): ,'Ronald'
MPRINT(DS2LIST): ,'Thomas'
MPRINT(DS2LIST): ,'William'
126 ;
127 quit;
NOTE: Table WORK.XX created, with 19 rows and 5 columns.
NOTE: PROCEDURE SQL used (Total process time):
real time 0.15 seconds
cpu time 0.06 seconds
Как вы можете видеть, он создал список имен через запятую и процитировал имена. Вы можете изменить разделитель, а также кавычки, которые используются. Количество элементов в списке не ограничено (мы использовали его в списках с количеством элементов более 100 тыс.), Поскольку список «потоковый» с помощью макроса, а не хранится в макропеременной. Единственное ограничение по размеру - это ограничение, определяемое размером запроса ODBC-сервера. Код к макросу немного страшен, но поместите его в папку автоматического вызова макросов и забудьте об этом.
Код макроса ниже:
/***************************************************************************
** PROGRAM: MACRO.DS2LIST.SAS
**
** UTILITY PROGRAM THAT DETECTS RETURNS A LIST OF FIELD VALUES FROM A
** DATASET IN DELIMITED FORMAT.
**
** PARAMETERS:
** iDs : THE LIBNAME.DATASET NAME THAT YOU WANT TO CHECK.
** iField : THE FIELD THAT CONTAINS THE VALUES YOU WANT RETURNED IN A
** DELIMITED FORMAT.
** iDelimiter: DEFAULT IS A COMMA. THE DELIMITER TO USE FOR THE RETURNED LIST.
** iDsOptions: ANY STANDARD DATASET OPTIONS THAT YOU WOULD LIKE TO APPLY SUCH
** AS A WHERE STATEMENT.
** iQuote : (0=NO,1=YES). DEFAULT=0/NO. DETERMINES WHETHER THE RETURNED
** LIST IS QUOTED OR NOT.
** iQuoteChar: (SINGLE,DOUBLE) DEFAULT=SINGLE. SPECIFIES WHETHER SINGLE0.
** OR DOUBLE QUOTES ARE USED WHEN QUOTING THE RETURNED LIST
**
*****************************************************************************
** VERSION:
**
** 1.0 ON: 05-FEB-2007 BY: ROBERT PENRIDGE
** CREATED.
** 1.1 ON: 29-APR-2008 BY: ROBERT PENRIDGE
** PUT IN ERROR CHECKING.
** ADDED AUTOMATIC TYPE DETECTION
** FIXED OUTPUT.
** 1.2 ON: 23-APR-2010 BY: ROBERT PENRIDGE
** CHANGED SO THAT OUTPUT SPOOLED. ALLOWS MACRO TO RETURN OUTPUT > 64KB.
** 1.3 ON: 12-MAY-2010 BY: ROBERT PENRIDGE
** ADDED PARAMETER CHECK AFTER I SPENT 10 MINUTES TRYING TO FIGURE OUT
** WHY MY CODE WAS RETURNING AN ERROR. DUH!
** 1.4 ON: 26-MAY-2010 BY: KN
** ADDED IQUOTE.
** 1.5 ON: 08-JUN-2010 BY: RP
** FIXED DCLOSE SO DATASET WOULD CLOSE PROPERLY AND RELEASE LOCK.
** 1.6 ON: 16-JUN-2010 BY: RP
** ADDED IQUOTECHAR PARAMETER
** 1.7 ON: 20-JUL-2010 BY: RP
** UNQUOTED RETURNED VALUES
** 1.8 ON: 11-OCT-2010 BY: KN
** MODIFIED TO ALLOW BLANK CHARACTER VALUES AND ALSO REMOVED TRAILING
** MODIFIED TO ALLOW PARENTHESES IN CHARACTER VALUES
*****************************************************************************/
%macro ds2list(iDs=, iField=, iDsOptions=, iDelimiter=%str(,), iQuote=0, iQuoteChar=single);
%local dsid pos rc result cnt quotechar;
%let result=;
%let cnt=0;
%if &iQuote %then %do;
%if "%upcase(&iQuoteChar)" eq "DOUBLE" %then %do;
%let quotechar = %nrstr(%");
%end;
%else %if "%upcase(&iQuoteChar)" eq "SINGLE" %then %do;
%let quotechar = %nrstr(%');
%end;
%else %do;
%let quotechar = %nrstr(%");
%put WARNING: MACRO.DS2LIST.SAS: PARAMETER IQUOTECHAR INCORRECT. DEFAULTED TO DOUBLE;
%end;
%end;
%else %do;
%let quotechar = ;
%end;
/*
** ENSURE ALL THE REQUIRED PARAMETERS WERE PASSED IN.
*/
%if "&iDs" ne "" and "&iField" ne "" %then %do;
%let dsid=%sysfunc(open(&iDs(&iDsOptions),i));
%if &dsid %then %do;
%let pos=%sysfunc(varnum(&dsid,&iField));
%if &pos %then %do;
%let rc=%sysfunc(fetch(&dsid));
%do %while (&rc eq 0);
%if "%sysfunc(vartype(&dsid,&pos))" = "C" %then %do;
%let value = %qsysfunc(getvarc(&dsid,&pos));
%if "%trim(&value)" ne "" %then %do;
%let value = %qsysfunc(cats(%nrstr(&value)));
%end;
%end;
%else %do;
%let value = %sysfunc(getvarn(&dsid,&pos));
%end;
/* WHITESPACE/CARRIAGE RETURNS REMOVED IN THE BELOW LINE */
/* TO ENSURE NO WHITESPACE IS RETURNED IN THE OUTPUT. */
%if &cnt ne 0 %then %do;%unquote(&iDelimiter)%end;%unquote("echar&value"echar.)
%let cnt = %eval(&cnt + 1);
%let rc = %sysfunc(fetch(&dsid));
%end;
%if &rc ne -1 %then %do;
%put WARNING: MACRO.DS2LIST.SAS: %sysfunc(sysmsg());
%end;
%end;
%else %do;
%put ERROR: MACRO.DS2LIST.SAS: FIELD &iField NOT FOUND IN DATASET %upcase(&iDs).;
%end;
%end;
%else %do;
%put ERROR: MACRO.DS2LIST.SAS: DATASET %upcase(&iDs) COULD NOT BE OPENED.;
%end;
%let rc=%sysfunc(close(&dsid));
%end;
%else %do;
%put ERROR: MACRO.DS2LIST.SAS: YOU MUST SPECIFY BOTH THE IDS AND IFIELD PARAMETERS TO CALL THIS MACRO.;
%end;
%mend;