2015-05-04 55 views
0

我想寫一個宏將創建一個新的表依賴於某些標準。用戶可以輸入一個數字或一系列數字來過濾原始數據。例如,如果起始數據集如下所示,則最終用戶可以選擇通過單個數字(即:其中Z = 1)或數字範圍(即:其中Z在1之間和5)。基於條件的SAS生成表?

X Y Z 
0 1 3 
2 7 9 
0  0 0 
2  1 1 

如果用戶想輸入一個數字範圍進行篩選時,會有值填充爲& start_range和& end_range。如果用戶想要對單個號碼進行過濾,則end_range將等於空。

我想要的代碼將檢查是否& end_range等於空。如果是,則where語句應爲列Z = & start_range的所有行創建新表。如果& end_range不等於null(它具有填充值),則where語句將爲列Z位於& start_range和& end_range之間的所有行創建新表。

對於單個值,(其中& start_range = 1和& end_range =」「),所得到的表將是:

X Y Z 
2  1 1 

對於一定範圍的值,(其中& start_range = 1和& end_range = 5),結果表將是:

X Y Z 
0 1 3 
2  1 1 

這是代碼我到目前爲止,不是100%肯定,如果語法是正確的如此開放的任何及所有的建議,謝謝!!:

%macro filter(); 

proc sql; 
      create table filtered_data AS 
      select raw_data.* 
      from raw_data 
      WHERE  

        %if &end_range NE '' %then %do; 
         Z between '&start_range' AND '&end_range'; 
        %end; 

        %else %do; 
         Z = '&start_range'; 
        %end; 

      quit; 

%mend; 

%filter(); 
+1

詢問有關特定問題的問題通常對本網站上的問答格式比一般排除故障請求更有效。不過,我有兩點建議。 (1)宏的參數應該在'%macro'語句中列出,並在調用宏時指定。 (2)您不需要重複整個查詢;你可以在'where'語句中放入'%if%then else'條件來控制只能改變的代碼行。這並沒有太大的影響,但它讓讀者清楚地知道代碼的哪一部分是有條件的。 – DWal

+0

如果宏調用(和參數)將手動寫入,那麼您可能只想將要使用的where子句傳遞給宏。如果您要生成對宏的動態調用並且不知道參數的值是什麼,這個練習只是非常值得的。 –

回答

0

而不是創建一個宏定義,我會建議解決您的問題,爲您的開始和結束範圍創建2個簡單的宏變量。開始範圍始終有一個有效的數字,但對於結束範圍,您可以在邏輯中進行編碼以在結束範圍值爲空/空的情況下獲取開始範圍值。看看下面的代碼,讓我知道它是否有幫助。

data raw_data; 
infile datalines missover; 
input X Y Z; 
datalines4; 
0 1 3 
2 7 9 
0  0 0 
2  1 1 
;;;; 
run; 
/*User enters the range*/ 
%let start_range=1; 
%let end_range=5; 

/*User entered data refining*/ 
%let end_range=%sysfunc(coalescec(&end_range,&start_range)); 

proc sql; 
create table filtered_data AS 
select * 
from raw_data 
where z between &start_range and &end_range 
; 
quit; 
proc print data=filtered_data;run; 

如果你還是喜歡創建宏定義來解決你的問題,然後嘗試在你的宏定義調整你的第一個%IF語句,並刪除您在WHERE語句應用到您的宏觀變量的單引號PROC SQL 。檢查更新的宏定義。

%macro filter; 
proc sql; 
      create table filtered_data AS 
      select raw_data.* 
      from raw_data 
      WHERE  
        %if %length(&end_range) %then %do; 
         Z between &start_range AND &end_range; 
        %end; 

        %else %do; 
         Z = &start_range; 
        %end; 
      quit; 
%mend; 
%filter;