Sas宏(如果否),然后基于输入参数

时间:2018-09-24 20:28:50

标签: sas

我正在编写一个带有两个参数的SAS宏,第一个是数据集的名称,第二个参数是一个将实际确定输出列之一的字符串:

%macro test(data, input_mth);
%if &comp_mth.=October %then %do;
cmp_basis=Last Fiscal End;
%end;
proc sql;
create table final as select &cmp_basis. as col1, data.col2 from data;
quit;
%mend;

%test(data, October);

基本上,我传入一个数据集,如果传入字符串“ October”,则输出将显示“ Last Fiscal End;作为第一列。如果我在一月份通过,它将显示“日历开始”等。

%if块给我错误:

Statement is not valid or it is used out of proper order.

3 个答案:

答案 0 :(得分:1)

只需通读代码即可发现一些问题。

首先,您的%IF语句引用的宏变量COMP_MTH在程序的任何地方都没有定义。我假设您打算改为引用您的输入参数之一。

%if &input_mth.=October %then %do;

第二,您的%DO/%END块中有数据步骤语句,但是您从未启动数据步骤。我假设您的意思是在那里创建一个宏变量。因此,请使用%let语句。

%let cmp_basis=Last Fiscal End; 

但是您还需要将该宏变量定义为local,否则您的宏将在调用程序的环境中覆盖具有相同名称的任何宏变量。

您还需要确保您的宏正在生成有效的SAS代码。因此,在您的SQL代码中,您有

select &cmp_basis. as col1

但是,如果我们只是将宏变量替换为上面分配的值,则会出现以下乱码:

select Last Fiscal End as col1

我假设您打算在此处创建一个字符变量,因此请加引号,以便生成一个字符常量。

select "&cmp_basis." as col1

您也有逻辑问题。当您不在十月份时,您想要的COL1值是多少?一种解决方法是在逻辑之前为宏变量设置默认值。但是也许您打算使用输入月份?所以也许您只需要添加一个%else子句?

您也永远不会使用其他输入参数。假设您的意思是传递SQL应该查询的数据集的名称。所以你想使用

from &data

但是从未定义您在DATA.col2中的SQL表别名。因此,请确保为输入表分配别名,或者对于此简单的一个表查询,只需在引用列名称时删除别名即可。

所以我们最终得到这样的东西:

%macro test(data, input_mth);
%local cmp_basis;
%if &input_mth.=October %then %do;
  %let cmp_basis=Last Fiscal End;
%end;
%else %let cmp_basis=&input_mth;
proc sql;
create table final as
  select "&cmp_basis." as col1
       , x.col2
  from &data x
;
quit;
%mend test;

对于这种简单的逻辑,我们可以省去多余的宏变量,而只需使用宏逻辑有条件地生成要用作COL1值的常数值即可。

%macro test(data, input_mth);
proc sql;
create table final as
  select 
%if &input_mth.=October %then "Last Fiscal End";
%else "&input_mth";
    as col1
  , x.col2
  from &data x
;
quit;
%mend test;

答案 1 :(得分:0)

我知道了,正确的语法是:

%macro test(data, input_mth);
%if &comp_mth.=prv %then %do;
%let cmp_basis=Last Fiscal End;
%end;
proc sql;
create table final as select "&cmp_basis." as col1, data.col2 from data;
quit;
%mend;

%test(data, October);

答案 2 :(得分:0)

您的代码有很多语句概念错误。如果您愿意给我更多有关您的需求的详细信息,我会更好地帮助您。 但我尝试了解您的问题,并提出了两种解决方案。

选项I

%macro test(data, input_mth);

    %if &comp_mth. = "October" %then %do;
        cmp_basis = Last /*Fiscal End*/;
    %end;

    proc sql;
        create table final as select 
            "&cmp_basis." as col1, 
             col2
        from &data.;
    quit;

%mend;

%test(data, October);

选项II

%macro test(data, input_mth);

    %if &comp_mth.=prv %then %do;
        %let cmp_basis = Last Fiscal End; /* this is a  Vector that contains string at Last, Fiscal and End*/
    %end;

    proc sql;
        create table final as select /* You create a table call final       */
        "&cmp_basis." as col1,       /* column call October                 */
        /* data.col2 */              /* this no have sense - what is this ? */
          col2                      /*Correct way to call col2 if it exists on data*/
        from &data.;                 /* Your data set, you call in macro    */
    quit;
%mend;

%test(data, October);