If statement SAS%If else宏

If statement SAS%If else宏,if-statement,macros,sas,If Statement,Macros,Sas,我对宏%IF%ELSE有问题。 我必须设置开关“Y”或“N”(将来会有更多),在这里这个变量运行不同部分的代码。 例如: 我应该怎么做才能使它工作?首先,您需要添加%global id\u wsadu到您的宏。这将使宏值在宏外部解析。然后,您需要通过传递参数来正确调用宏,例如%Set\u id\u wsadu('Y')。在这里: %macro Set_id_wsadu(Czy_Max); %global id_wsadu; %if &Czy_Max. = 'N' %then

我对宏%IF%ELSE有问题。 我必须设置开关“Y”或“N”(将来会有更多),在这里这个变量运行不同部分的代码。 例如:


我应该怎么做才能使它工作?

首先,您需要添加
%global id\u wsadu到您的宏。这将使宏值在宏外部解析。然后,您需要通过传递参数来正确调用宏,例如
%Set\u id\u wsadu('Y')
。在这里:

%macro Set_id_wsadu(Czy_Max);
%global id_wsadu;
   %if &Czy_Max. = 'N' %then
      %do;
        %let id_wsadu = 3;/*Tu wpisujemy ręcznie id wsadu które nas interesuje*/
    %end;

   %else %if &Czy_Max. = 'Y' %then
      %do;
            Proc SQL NOPRINT;
            Select MAX(id_wsadu) Into :id_wsadu
            From Work.REKORD_RACH;
            quit;
      %end;
%mend;
%Set_id_wsadu('Y');

%put &id_wsadu;

PROC SQL;
   CREATE TABLE REKORD_RACH_GET AS 
   SELECT *
   FROM REKORD_RACH
   WHERE ID_WSADU = &id_wsadu.;
QUIT;

首先,您需要添加
%global id\u wsadu到您的宏。这将使宏值在宏外部解析。然后,您需要通过传递参数来正确调用宏,例如
%Set\u id\u wsadu('Y')
。在这里:

%macro Set_id_wsadu(Czy_Max);
%global id_wsadu;
   %if &Czy_Max. = 'N' %then
      %do;
        %let id_wsadu = 3;/*Tu wpisujemy ręcznie id wsadu które nas interesuje*/
    %end;

   %else %if &Czy_Max. = 'Y' %then
      %do;
            Proc SQL NOPRINT;
            Select MAX(id_wsadu) Into :id_wsadu
            From Work.REKORD_RACH;
            quit;
      %end;
%mend;
%Set_id_wsadu('Y');

%put &id_wsadu;

PROC SQL;
   CREATE TABLE REKORD_RACH_GET AS 
   SELECT *
   FROM REKORD_RACH
   WHERE ID_WSADU = &id_wsadu.;
QUIT;

您在宏变量范围和宏变量值的混淆方面遇到了问题

首先定义了一个全局宏变量(因为您在任何特定宏范围之外运行了
%let

然后定义了一个使用相同宏变量名称作为参数的宏

%macro Set_id_wsadu(Czy_Max);
这将创建一个名为
Czy_Max
的本地宏变量,该变量将隐藏同名全局宏变量的值。在调用宏时,只需将全局宏变量的值传递到宏中,即可使此设置正常工作。像这样:

%Set_id_wsadu(&Czy_Max);
%if not %symexist(id_wsadu) %then %global id_wsadu;
尽管对全局和局部宏变量使用不同的名称可能不那么容易混淆

第二,您正在为宏内部的宏变量设置一个值,而没有明确定义SAS应将该宏变量视为局部变量还是全局变量

%let id_wsadu = 3;
如果宏变量
id\u wsadu
在分配运行时已经存在,则其值将被更新。否则,它将导致创建一个本地宏变量,该变量将在宏完成运行时停止存在。您可以通过确保在调用宏之前定义宏变量来解决此问题

%let id_wsadu = ;
%Set_id_wsadu(&Czy_Max);
或者,您可以在宏中添加
%global
语句,以便在为宏变量赋值之前在全局符号表中定义宏变量。但是,如果从另一个已将该宏变量创建为本地变量的宏调用该宏,则会导致问题。不能使用与现有本地宏变量相同的名称创建新的全局宏变量。为了防止出现这种错误,可以在使宏变量成为全局变量之前测试它是否已经存在。像这样:

%Set_id_wsadu(&Czy_Max);
%if not %symexist(id_wsadu) %then %global id_wsadu;
最后,为什么要在宏变量的值中添加引号?看起来您一直在这样做,因此代码应该可以工作,但这可能意味着您不理解引号实际上是宏变量值的一部分。这与SAS代码不同,SAS代码中需要引号,以便编译器知道字符串文字、数字文字和变量名或SAS关键字之间的差异。因此,在SAS代码中,文字周围的引号不是值的一部分

因此,在数据步骤中,您可以使用不同的外部引号运行类似这样的代码,并且文本将匹配

if 'A' = "A" then
但在宏代码中,引号是值的一部分,因此如果您尝试此代码:

%if 'A' = "A" %then 

这两个值是不同的,因为
不等于

您在宏变量范围界定和宏变量值混淆方面遇到了问题

首先定义了一个全局宏变量(因为您在任何特定宏范围之外运行了
%let

然后定义了一个使用相同宏变量名称作为参数的宏

%macro Set_id_wsadu(Czy_Max);
这将创建一个名为
Czy_Max
的本地宏变量,该变量将隐藏同名全局宏变量的值。您只需在调用宏时将全局宏变量的值传递到宏中即可完成此设置。如下所示:

%Set_id_wsadu(&Czy_Max);
%if not %symexist(id_wsadu) %then %global id_wsadu;
尽管对全局和局部宏变量使用不同的名称可能不那么容易混淆

第二,您正在为宏内部的宏变量设置一个值,而没有明确定义SAS应将该宏变量视为局部变量还是全局变量

%let id_wsadu = 3;
如果宏变量
id\u wsadu
在该分配运行时已存在,则其值将被更新。否则,将导致创建一个本地宏变量,该变量在宏运行结束时将不再存在。您可以通过在调用宏之前确定定义宏变量来解决此问题

%let id_wsadu = ;
%Set_id_wsadu(&Czy_Max);
或者,您可以在宏中添加一条
%global
语句,以便在为其赋值之前在全局符号表中定义宏变量。但是,如果您从另一个已将该宏变量创建为本地宏变量的宏中调用该宏,则会导致问题。您无法创建与exi同名的新全局宏变量sting局部宏变量。为了防止出现此错误,可以在使其成为全局变量之前测试宏变量是否已存在。如下所示:

%Set_id_wsadu(&Czy_Max);
%if not %symexist(id_wsadu) %then %global id_wsadu;
最后,为什么要将引号添加到宏变量的值中?看起来您一直在这样做,因此代码应该可以工作,但这可能意味着您不理解引号实际上是宏变量值的一部分。这与SAS代码不同,SAS代码需要引号,以便编译器知道字符串文字、数字文字和变量名或SAS关键字之间的区别。因此,在SAS代码中,文字周围的引号不是值的一部分

因此,在数据步骤中,您可以使用不同的外部引号运行类似这样的代码,并且文本将匹配

if 'A' = "A" then
但在宏代码中,引号是值的一部分,因此如果您尝试此代码:

%if 'A' = "A" %then 

这两个值不同,因为
不等于

您定义的宏变量(id_wsadu)是本地宏变量,它只存在于宏程序中,将从宏变量表中删除。如果要使其成为全局变量,请在定义的宏变量之前添加%global Id\u wsadu。可能会重复此宏变量。谢谢盛林的回答!宏变量(id_wsad