【问题标题】:SAS macros: using macros in proc sqlSAS 宏:在 proc sql 中使用宏
【发布时间】:2012-04-10 15:11:59
【问题描述】:

如何在 SQL 中使用宏? (对于每一件事,都被选中)

我的意思是这样的:

&VarTable 是一个表,其中有两个变量:(例如)LibTable

&VarTable 中的每个观察都是表的名称:Lib.Table

我要为每张桌子做事:

1) 存在吗?

2) 排序

最后一个条件: 每个表(如果存在)都有一个变量&VarField

   %macro mSortedTable(vLib,vTab,vVar);
        %if %sysfunc(exist(&vLib..&vTab)) %then %do;
             proc sort data = &vLib..&vTab;
                 by &vVar; 
             run;
             &vLib..&vTab
        %end; 
        %else %do; "" %end;
   %mend mSortedTable;

   proc sql noprint;
          select %mSortedTable(vLib=Lib,vTab=Table,vVar=&VarField)
              into: AccumVar separated by " "
          from &VarTable;
   quit;

如何使用 sql 和宏来做到这一点?

【问题讨论】:

  • 避开第一个问题:当然,这段代码不起作用
  • 那么对于一个包含对库和数据集名称的观察的数据集,您想对每个数据集执行操作吗?并且要将每个变量名放入宏中?
  • 是的。我的同伴说我可以做到这一点,使用猫和宏生成:proc sql noprint; select cats('%mSortedTable(',Lib,',',Table,',',&VarField,')') into: AccumVar separated by " " 但这个变体不能在数据步中使用,所以我决定用两个宏使用相同的结构,首先排序,另一个将命名Lib.Table

标签: sql sas sas-macro


【解决方案1】:

你必须使用 sql 和宏吗?一个简单的数据步骤和call execute 可以满足您的需要。

下面是一个示例,它采用具有要处理的表列表的数据集,检查表是否存在,如果存在,则按 &VarField 对其进行排序。如果需要,这可以很容易地扩展为通过一组自定义变量对每个表进行排序。

如果表不存在,则生成警告消息。

/* create fake data */
data testdat;
length lib $8 table $32;
input lib $ table $;
datalines;
work test1
work test2
work test3
work doesnotexist
;
run;
/* create 3 data sets */
data work.test1 work.test2 work.test3;
input var1 var2 var3;
datalines;
1 34 8
2 54 5
12 5 6
;
run;
/* end create data */

%let VarTable=work.testdat;
%let VarField=var2 var3;


data _null_;
  set &VarTable;
  dsname=catx('.',lib,table);
  if exist(dsname) then do;
    call execute("proc sort data=" || strip(dsname) || "; by &VarField; run;");
  end;
  else do;
    put "WARNING: The data set does not exist: " lib= table=;
  end;
run;

【讨论】:

  • hmm.. 你写的代码很简单:) 但我不明白,如果这个代码像它一样工作,它应该对我有用。我对在你的代码中使用宏感到困惑,请告诉我,call execute 在 perl-php-js 等语言中是否像 eval 函数一样工作?
  • 是的,它类似于 perl eval,SAS 解析字符串,然后像 SAS 会话一样提交解析的代码。由于数据步骤是逐行操作的,所以call execute每行符合if条件的数据都会提交一次。
【解决方案2】:

调用执行是一个很好的解决方案,但是如果“执行”的数据步骤代码很复杂(在这个例子中不是这样),我觉得很难调试。

另一种方法是将所有变量放入宏变量中,然后在宏do-loop中循环;

(基于@cmjohns 数据)

/* create fake data */
data testdat;
 length lib $8 table $32;
 input lib $ table $;
 datalines;
 work test1
 work test2
 work test3
 work doesnotexist
 ;
run;

/* create 3 data sets */
data work.test1 work.test2 work.test3;
 input var1 var2 var3;
 datalines;
 1 34 8
 2 54 5
 12 5 6
 ;
run;
/* end create data */

%let VarTable=work.testdat;
%let VarField=var2 var3;

proc sql noprint;
 select count(lib)
 into :cnt
 from &vartable;

 %Let cnt=&cnt;

 select strip(lib), strip(table)
 into :lib1 - :lib&cnt, :table1 - :table&cnt
 from &vartable;
quit;

%Macro test;
 %Do i = 1 %to &cnt;

  %Let lib=&&lib&i;
  %Let table=&&table&i;
  %Let dsn=&lib..&table;

  %if %sysfunc(exist(&dsn)) %then %do;
   Proc sort data=&dsn;
    by &varfield;
   run;
  %end;
  %else %do;
   %put WARNING: The data set does not exist: &dsn;
  %end;

 %end;
%Mend;
%test

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-21
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多