Автоматизация сканирования и поиска имен таблиц/объектов в SAS

Хорошо, я начну с проблемы: у меня каждую неделю создаются таблицы продуктов, которые называются в формате:

products_20130701
products_20130708
.
.
.

Я пытаюсь автоматизировать некоторый анализ кампании, чтобы мне не приходилось каждую неделю вручную менять имя таблицы в коде, чтобы использовать ту таблицу продуктов, которая будет первой после максимальной даты окончания моей кампании.

e.g

%put &max_enddate.; 
/*20130603*/

мои таблицы продуктов в июне:

products_20130602
*products_20130609*
products_20130616
products_20130623

в этом случае я хотел бы использовать вторую таблицу в списке, игнорируя таблицы продуктов за более чем 12 месяцев и просто выбирая таблицу, дата которой находится сразу после моего макроса max_enddate.

Я весь день гуглил, и я в тупике, поэтому ЛЮБОЙ совет будет очень признателен.

Спасибо!


person Charlotte Stevens    schedule 02.08.2013    source источник
comment
Шарлотта - если вы довольны своим ответом, отметьте его как правильный!   -  person Allan Bowe    schedule 08.08.2013


Ответы (3)


SQL-решение:

data product_20130603;
run;

data product_20130503;
run;

data product_20130703;
run;

%let campdate=20130601;

proc sql;
  select min(memname) into :datasetname from dictionary.tables 
  where libname='WORK' and upcase(scan(memname,1,'_'))='PRODUCT' and
  input(scan(memname,2,'_'),YYMMDD8.) ge input("&campdate.",YYMMDD8.);
quit;

Теперь у вас есть &datasetname, который вы можете использовать в операторе set, поэтому

данные мой_анализ; установить     (что бы вы ни делали); бежать;

Измените «WORK» на соответствующее имя библиотеки, и если есть какие-либо другие ограничения, добавьте их. Вы можете получить некоторые предупреждения о недопустимых датах, если у вас есть product_somethingnotadate, но это не должно иметь значения.

Как это работает: Dictionary.tables представляет собой список всех таблиц во всех именах библиотек, к которым вы обращались (то же самое, что и sashelp.vtable, но доступно только в PROC SQL). Сначала выбираются все строки, имя которых имеет дату, большую или равную дате окончания вашей кампании; затем он берет min(memname) из этого. Memname — это, конечно, строка, но в строках, которые идентичны, за исключением числа, вы все равно можете использовать min и получить ожидаемый результат.

person Joe    schedule 02.08.2013
comment
это очень кратко, я пытался быть умным и избегать использования SQL, используя цикл для сканирования всех имен таблиц (или что-то в этом роде?), но это гораздо менее сложно и не нужно. я просто подожду, чтобы узнать больше о циклах do по мере необходимости. еще раз спасибо :) - person Charlotte Stevens; 08.08.2013

Это, вероятно, не подходит для вашего приложения, однако я нахожу это очень полезным для наборов данных, которые у меня есть, поскольку они абсолютно должны существовать каждое воскресенье, и я оцениваю существование набора данных в начале моего кода. Если они не существуют, он отправляет электронное письмо нашим ИТ-специалистам, в котором сообщается, что файл отсутствует и его необходимо заново создать\восстановить.

%LET DSN = PRODUCTS_%SYSFUNC(PUTN(%SYSFUNC(INTNX(WEEK.2,%SYSFUNC(INPUTN(&MAX_ENDDATE.,YYMMDD8.)),0,END)),YYMMDDN8.));

С другими приведенными выше предложениями они дадут вам результаты только для существующих наборов данных, поэтому, если тот, который вы должны были использовать, был удален, он возьмет следующий и запустит задание независимо.

person user2337871    schedule 05.08.2013

Во-первых, получить все возможные таблицы:

data PRODUCT_TABLES;
    set SASHELP.VTABLE (keep=libname memname);
    *get what you need, here i keep it simple;
    where lowcase(substr(memname,1,9))='products_';
run;

Затем отсортируйте его по дате, что легко сделать из-за формата имен ваших наборов данных.

proc sort data=PRODUCT_TABLES;
    by memname;
run;

Наконец, вам просто нужно получить первую запись, где дата достаточно велика.

data _NULL_;
    set PRODUCT_TABLES;
    *compare to your macro variable, note that i keep it as simple as possible and let SAS implicitly convert to numeric;
    if substr(memname,10,18)>=symgetn("max_enddate") then do;
        *set your match into a macro variable, i have put together the libname and memname here;
        call symput("selectedTable",cats(libname,'.',memname));
        stop; *do not continue, otherwise you will output simply the latest dataset;
    end;
run;

Теперь вы можете просто поместить переменную макроса, если хотите использовать соответствующий набор данных, например:

data SOME_TABLE;
    set &selectedTable.;
    /*DO SOME STUFF*/
run;
person mvherweg    schedule 02.08.2013
comment
Спасибо за это, я новичок в SAS, поэтому я не уверен, что нужно ввести в этот первый набор данных: data PRODUCT_TABLES; установить SASHELP.VTABLE (keep=libname memname); где нижний регистр (substr (memname, 1,9)) = 'products_'; бежать; Я не уверен, что использовать в команде set, так как я хочу, чтобы она искала во всей библиотеке таблицы, начинающиеся с products_dateid - person Charlotte Stevens; 02.08.2013
comment
ну, как я написал в примере, он найдет все наборы данных, которые начинаются с products_. Вы можете адаптировать предложение where, используя регулярные выражения, чтобы найти все наборы данных, которые имеют следующую структуру: (1) начинается с: products_ и (2) сопровождается 8 цифрами. Но я подозреваю, что вы тоже новичок в регулярных выражениях, не так ли? - person mvherweg; 02.08.2013
comment
ой, мой плохой: / как я уже сказал: новичок, вы знаете, как я написал бы это как цикл выполнения, если бы мне когда-нибудь понадобится? так что, возможно, что-то вроде: do loop; я = &max_enddate + 1; если существует(products_&i.), то сделать что-нибудь еще; снова зациклиться; ? как видите, я понятия не имею о синтаксисе... - person Charlotte Stevens; 02.08.2013