迭代查询的行创建新表

Iterating rows of a query creating new tables

我有一个 table 包含项目中其他几个 table 的名称。

如下列表table:

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
;

我需要在这个项目的所有 table 中通过查询执行某种处理。

所以我写了一个宏,通过更改 table 的名称来执行查询。

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

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

%MAKE_TABLE;

有效,但我认为不是最有效的方法

所以我写了一个宏,通过更改 table 的名称来执行查询。

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

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

%MAKE_TABLE;

有效,但我认为这不是最有效的方法

但是,此方法依赖于 LIST 中的一个 ID table。

Select table 命名 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 &SQLOBS;

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

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

  %end;

%mend;

%do_same_query_each_table

一个正常的模式是制作一个将 table 名称作为参数的宏。

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

然后您可以使用 CALL EXECUTE 为您的 LIST 中的每个观察生成一个宏调用 table。

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

%make_table 周围添加 %nrstr() 将确保在数据步骤之后将宏调用本身推入堆栈 运行 而不是它生成的代码。这将使日志更易于阅读。当宏具有依赖于评估执行宏生成的代码的结果的逻辑时,它还将防止计时问题。