динамически исключать имена столбцов в макросе proc sql - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть инструкция proc sql в макрос-функции, которая выбирает имена столбцов из dictionary.columns.Я хотел бы исключить имена столбцов на основе нескольких строковых шаблонов, которым переданы аргументы - см. Ниже

%symdel keepnames;

%macro test(data=, col=);
    %global keepnames;

    %let data_lib = %sysfunc(upcase(%sysfunc(scan("&data", 1, "."))));
    %let data_data = %sysfunc(upcase(%sysfunc(scan("&data", 2, "."))));
    %put &data_lib;
    %put &data_data;

    proc sql noprint;
        select name into :keepnames separated by " "
        from    dictionary.columns
        where   libname = "&data_lib" and
        memname = "&data_data" and
        upcase(name) not like upcase("&col.");
    quit;
%mend test;

%test(data=sashelp.cars, col=mpg w)
%put &keepnames;

В идеале аргумент col должен превращаться в %mpg%, %w%, что исключает любые имена столбцов с mpg илиw в их имени.

Есть пара проблем, с которыми я сталкиваюсь.Во-первых, я не могу понять, как скрыть % от макропроцессора.Я пытался использовать %str() несколькими способами, но безуспешно.Во-вторых, я не могу легко добавить символы % вокруг слов в аргументе col.Любая помощь приветствуется!

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

Я использовал оператор содержимого в следующем и перебрал аргументы в col для генерации отдельных тестов для каждого исключения.Почему-то у меня нет машин, поэтому я использовал класс:

%symdel keepnames;

%macro test(data=, col=);
    %global keepnames;

    %let data_lib = %sysfunc(upcase(%sysfunc(scan("&data", 1, "."))));
    %let data_data = %sysfunc(upcase(%sysfunc(scan("&data", 2, "."))));
    %put &data_lib;
    %put &data_data;
    %let i = 1;
    %let exclusion = %scan(&col,&i);

    proc sql noprint;
        select name into :keepnames separated by " "
        from    dictionary.columns
        where   libname = "&data_lib" and
        memname = "&data_data"

        %do %while(&exclusion ne );
            and upcase(name) not contains upcase("&exclusion")

            %let i = %eval(&i + 1);
            %let exclusion = %scan(&col,&i);
        %end;
        ;
    quit;
%mend test;

option mprint;
%test(data=sashelp.class, col=ame x)
%put &keepnames;

%test(data=sashelp.class)
%put &keepnames;

%test(data=sashelp.class, col=e)
%put &keepnames;
0 голосов
/ 13 декабря 2018

Измените имя параметра макроса, чтобы оно было лучше информирующим, например,

%macro fetch_names (data=, dropPattern=, resultVar=fetchedNames)
   ...
%mend;

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

 %let fetchedNames = ;
 %fetch_names (
   data = sashelp.cars
 , dropPattern = mpg|w     /* <------- regular expression pattern */
 , resultVar = fetchedNames
 )

Внутренняя часть макроса будет аналогичной.

  • изменить
    into :keepnames на
    into :&resultVar
  • изменить
    upcase(name) not like upcase("&col.")до
    not prxmatch("/&dropPattern./i", name)
...