[英]SAS macro passing SQL or code to use in macro
我相對較不熟悉SAS宏編程,主要是使用它來使代碼更“干凈”並避免重復代碼中的錯誤。
我已經做了一些谷歌搜索,但是還沒有找到簡單的方法。
我首先有2個問題-如何將列列表傳遞給宏?
我希望宏在通用代碼中看起來像這樣:
proc sql;
create table &usefulTable as
%DoStuff('col1, col3, col9', 'col1 = 12 or (col2 between 1 and 3)')
;
基本上,我將列值作為第一個參數,而where子句作為第二個參數。
是否可以使宏通過第一個參數作為列名,並使用第二個參數作為where子句的一部分,從而使宏成為可能?
%MACRO DoStuff(col, cond);
select
&col separated by ',' ,
'source1' as source
from &someNiceTable
where &cond
union
select
&col separated by ',' ,
'source2' as source
from &someNiceOtherTable
where &cond
%mend;
上面是示例基本宏,顯示了我打算執行的類似功能,在這種情況下,將2個表合並,同時添加新列,定義從哪個表中設置記錄。 基本上,將始終對多個表應用相同的條件,然后將它們與並聯添加一個額外的列。
很高興對此有所幫助。
老實說,我面臨的最大問題是傳遞are變量,因為我可以將列名用作宏中的硬編碼值,但是問題在於where子句,因為它會定期更改。
您走在正確的軌道上。 您在部分引用這些參數是正確的,否則第一個參數(列的列表)將被解釋為3個單獨的參數,而另一個參數(條件為)將被解釋為名為col1
的關鍵字參數。 但是,這將要求您在宏定義中dequote
這些參數。 一種更簡單的方法是在宏調用中使用%str()
。
您在proc sql
使用separated by
符的用法也不正確。 與into
語句一起使用,可將select
語句中的值存儲到宏變量中。
您的宏應如下所示:
%MACRO DoStuff(col, cond);
select
&col,
'source1' as source
from &someNiceTable
where &cond
union
select
&col,
'source2' as source
from &someNiceOtherTable
where &cond
%mend;
調用應該是這樣的:
proc sql;
create table &usefulTable as
%DoStuff(%str(col1, col3, col9), %str(col1 = 12 or (col2 between 1 and 3)))
;
quit;
如果將值作為帶引號的字符串傳遞,並且希望不帶引號使用它們,則可以使用%SYSFUNC()
宏函數調用DEQUOTE()
函數。
%MACRO DoStuff(col, cond);
select %sysfunc(dequote(&col))
, 'source1' as source
from &someNiceTable
where %sysfunc(dequote(&cond))
;
%mend;
請注意,這還將處理刪除您可能使用的所有宏引號,而不是文字引號字符,以保護嵌入式逗號。
請注意,對於您的COND變量,您可以只在條件周圍添加()
而不是引號或宏引號,以防止宏調用引起混淆。
因此,您的通話可能看起來像其中之一:
%DoStuff(col='col1, col3, col9',cond=(col1 = 12 or (col2 between 1 and 3)))
%DoStuff(col=%str(col1, col3, col9),cond=(col1 = 12 or (col2 between 1 and 3)))
我發現最好傳遞變量列表,並在變量之間使用空格而不是逗號。 這樣,它們可以直接在常規SAS語句中使用。 只有SQL提出了使用逗號作為分隔符的煩人要求。 因此,使宏代碼添加逗號,以便宏的用戶無需擔心會添加逗號。
%macro mymac(dsn,varlist);
%local sqllist;
%let sqllist=%sysfunc(translate(%sysfunc(compbl(&varlist)),%str(,),%str( )));
proc print data=&dsn ;
var &varlist ;
run;
proc sql ;
select &sqllist from &dsn ;
quit;
%mend mymac ;
您還可以在值列表中使用其他字符(例如|
或^
)作為分隔符。
%do i=1 %to %sysfunc(countw(&list,|));
%let word=%scan(&list,&i,|);
...
%end;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.