2012-04-10 206 views
1

如何在SQL中使用宏? (对于每一件事情,那选择)SAS宏:在宏程序中使用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和宏来做到这一点?

+0

回避的第一个问题:这个代码不工作,当然 – gaussblurinc 2012-04-10 15:12:43

+0

的所以用含有库的观测和数据的数据集设置名称要执行的操作在每个数据集?你想把每个变量名称放入一个宏? – 2012-04-10 15:30:21

+0

是的。我的同事说我,我可以做到这一点,使用猫和macrogeneration: proc sql noprint; 'select cats('%mSortedTable(',Lib,',',Table,',',&VarField,')')into:AccumVar由“”分隔' 但这个变体不能用在datastep中,所以我决定使用与两个宏相同的结构,首先将排序,另一个将名称'Lib.Table' – gaussblurinc 2012-04-12 07:49:02

回答

2

你必须使用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; 
+0

嗯..你写了简单的代码:)但我不明白,如果这个代码工作,它应该工作我。我对你的代码中使用宏感到困惑,请告诉,像perl-php-js这样的语言中的'call execute'工作像'eval'函数一样吗? – gaussblurinc 2012-04-12 07:55:42

+0

是的,它类似于perl'eval',SAS解析字符串,然后提交解析后的代码,就好像它是SAS会话一样。由于数据步骤一行一行地操作,因此对于匹配if条件的每行数据提交一次'call execute'。 – cmjohns 2012-04-12 11:54:51

1

呼叫执行是一个很好的解决方案,但是如果数据码步骤正在“执行”是复杂的(它是不是在该示例中),我觉得很难调试。

另一种方法是将所有变量放入宏变量中,然后在宏do循环中遍历它们;

(上@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