SAS宏 - 将多个表合并为一个表,由另一个表控制

时间:2012-06-20 10:53:33

标签: macros sas sas-macro

我迟到了一个项目,想要编写一个宏来规范化一些数据以便导出到SQL Server。

有两个控制表......
- 表1 (customers)有一个客户唯一标识符列表
- 表2 (hierarchy)有一个表名列表

然后有n个附加表。一个用于(hierarchy) 中的每个记录(在SourceTableName字段中命名)。以......的形式 - CustomerURN,Value1,Value2

我想将所有这些表组合成一个表(sample_results),形式为...
- SourceTableName,CustomerURN,Value1,Value2

但是,应该复制的唯一记录应该是(customers)表中存在的CustomerURN。


我可以使用proc sql以硬编码格式执行此操作,例如......

proc sql;
insert into
  SAMPLE_RESULTS
select
  'TABLE1',
  data.*
from 
  Table1    data
INNER JOIN
  customers
    ON data.CustomerURN = customers.CustomerURN

<repeat for every table>

但每周都有新记录添加到hierarchy表中。

有没有办法编写一个从hierarchy表中获取表名的循环,然后调用proc sql将数据复制到sample_results

2 个答案:

答案 0 :(得分:1)

您可以将所有层次结构表连接在一起,并执行单个SQL连接

proc sql ;
  drop table all_hier_tables ;
quit ;

    %MACRO FLAG_APPEND(DSN) ;
      /* Create new var with tablename */
      data &DSN._b ;
        length SourceTableName $32. ;
        SourceTableName = "&DSN" ;
        set &DSN ;
      run ;

      /* Append to master */
      proc append data=&DSN._b base=all_hier_tables force ; 
      run ;
    %MEND ;

    /* Append all hierarchy tables together */
    data _null_ ;
      set hierarchy ;
      code = cats('%FLAG_APPEND(' , SourceTableName , ');') ;
      call execute(code); /* run the macro */
    run ;

    /* Now merge in... */
    proc sql;
    insert into
      SAMPLE_RESULTS
    select
      data.*
    from 
      all_hier_tables data
    INNER JOIN
      customers
        ON data.CustomerURN = customers.CustomerURN
quit;

答案 1 :(得分:0)

另一种方法是创建一个视图,使其始终反映元数据表中的最新数据。调用执行函数用于从层次结构数据集中读取表名。这是一个您应该能够修改以适合您的数据的示例,最后一位代码是您的相关代码。

data class1 class2 class3;
set sashelp.class;
run;

data hierarchy;
input table_name $;
cards;
class1
class2
class3
;
run;

data ages;
input age;
cards;
11
13
15
;
run;

data _null_;
set hierarchy end=last;
if _n_=1 then call execute('proc sql; create view sample_results_view as ' );
if not last then call execute('select * from '||trim(table_name)||' where age in (select age from ages) union all ');
if last then call execute('select * from '||trim(table_name)||' where age in (select age from ages); quit;');
run;