簡體   English   中英

SAS宏傳遞要在宏中使用的SQL或代碼

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM