2012-04-10 205 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