Повторяющиеся строки запроса, создающие новые таблицы

#sas #sas-macro

#sas #sas-макрос

Вопрос:

У меня есть таблица, содержащая имена нескольких других таблиц в проекте.

Как показано в таблице СПИСКА ниже:

 DATA WORK.LIST; INPUT TABLE_ID TABLE_NAME : $CHAR25.;
DATALINES;
1 CUSTOMERS
2 PRODUCTS
3 ORDERS
;

DATA WORK.CUSTOMERS; INPUT CUSTOMER_ID CUSTOMER_NAME $;
DATALINES;
1 David
2 Jose
3 Marcos
4 Josue
;

DATA WORK.PRODUCTS; INPUT PRODUCT_ID PRODUCT_NAME  $;
DATALINES;
41574 Tevision
35741 Refrigerator
74585 Cooker
;

DATA WORK.ORDERS; INPUT ORDER_ID CUSTOMER_ID PRODUCT_ID;
DATALINES;
741 1 41574
987 4 74585
888 4 35741
111 2 41574
;
  

Мне нужно выполнить определенную обработку с помощью запроса во всех таблицах этого проекта.

Итак, я написал макрос, который выполняет запросы, изменяя имена таблиц.

 PROC SQL NOPRINT; SELECT COUNT(*) INTO : NUM  FROM WORK.INICIO; QUIT;

%MACRO MAKE_TABLE;
    %DO i = 1 %TO amp;num;
        PROC SQL NOPRINT;
            SELECT TABLE_NAME INTO : VAR_TABLE_NAME
            FROM WORK.LIST
            WHERE TABLE_ID = amp;i.;
        QUIT;
        PROC SQL;
            CREATE TABLE TABLE_amp;i AS
            SELECT *
            FROM WORK.amp;VAR_TABLE_NAME;
        QUIT;
    %END;
%MEND;

%MAKE_TABLE;
  

Это работает, но я думаю, что это не самый эффективный метод.

Комментарии:

1. Я добавил решение, которое использовал для своего вопроса. Но я думаю, что это не самый эффективный.

Ответ №1:

Обычным шаблоном для этого является создание макроса, который принимает имя таблицы в качестве параметра.

 %MACRO MAKE_TABLE(TABLE_NAME);
...
  FROM WORK.amp;TABLE_NAME
...
%MEND MAKE_TABLE;
  

Затем вы можете использовать CALL EXECUTE для генерации одного вызова макроса для каждого наблюдения в вашей таблице СПИСКА.

 data _null_;
   set list;
   call execute(cats('%nrstr(%make_table)(',table_name,')'));
run;
  

Добавление %nrstr() вокруг %make_table гарантирует, что сам вызов макроса будет помещен в стек для запуска после шага данных вместо кода, который он генерирует. Это облегчит чтение журнала. Это также предотвратит проблемы с синхронизацией, когда у макроса есть логика, которая зависит от оценки результатов выполнения кода, который генерирует макрос.

Ответ №2:

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

Пример:

 %macro do_same_query_each_table;

  proc sql noprint;
    select table_name into :names separated by ' ' from work.list;
  quit;

  %local i table_name;
  %do i = 1 %to amp;SQLOBS;

    %let table_name = %scan(amp;names,amp;i);

    proc sql;
      ...query here...
        ... from amp;table_name ...
      ...query here...
    quit;

  %end;

%mend;

%do_same_query_each_table
  

Комментарии:

1. Этот метод более эффективен, поскольку он выполняет одну процедуру SQL на каждой итерации. Метод, который я сделал, выполняет два процесса SQL на каждой итерации.

Ответ №3:

Итак, я написал макрос, который выполняет запросы, изменяя имена таблиц.

 PROC SQL NOPRINT; SELECT COUNT(*) INTO : NUM  FROM WORK.INICIO; QUIT;

%MACRO MAKE_TABLE;
    %DO i = 1 %TO amp;num;
        PROC SQL NOPRINT;
            SELECT TABLE_NAME INTO : VAR_TABLE_NAME
            FROM WORK.LIST
            WHERE TABLE_ID = amp;i.;
        QUIT;
        PROC SQL;
            CREATE TABLE TABLE_amp;i AS
            SELECT *
            FROM WORK.amp;VAR_TABLE_NAME;
        QUIT;
    %END;
%MEND;

%MAKE_TABLE;
  

Это работает, но я считаю, что это не самый эффективный метод.

Однако этот метод зависит от идентификатора в таблице СПИСКА.

Комментарии:

1. Итак, вы хотите изменить разумные имена таблиц на какое-то относительно анонимное имя? Что вы хотите от TABLE_ID ?

2. Нет. На самом деле, идея состоит в том, чтобы запускать SQL-запрос для каждой таблицы в TABLE_NAME, используя PROC SQL. В этом примере я сделал «SELECT * FROM», но это был всего лишь пример (я мог бы использовать GROUP BY , WHERE и т. Д.). Суть идеи состоит в том, чтобы иметь таблицу, содержащую имена нескольких других таблиц, и выполнять итерации по этой таблице, генерируя запросы с помощью PROC SQL. Важно то, как сообщить имя таблицы в «FROM WORK.amp;VAR_TABLE_NAME».