通过数据步骤进行SAS变量连接

Yoh*_*Yoh 2 variables sas datastep sas-macro

我正在寻找一种方法来创建一个包含数据集的某些值的字符串变量,同时通过数据步骤.

示例数据集work.test:

AddToStringYN    Value
     Y           One
     Y           Two
     N           Three
     Y           Four
     N           Five
Run Code Online (Sandbox Code Playgroud)

所以最后,变量看起来像:OneTwoFour(甚至更好的FourTwoOne).这看起来很简单,但我似乎无法找到办法.我也尝试使用像这样的宏变量:

%let stringvar=;
Data _null_;
  set work.test;
  if AddToStringYN = "Y" then do;
    call symput('stringvar',"&stringvar" || strip(value));
  end;
Run;
Run Code Online (Sandbox Code Playgroud)

但这给了:

GLOBAL STRINGVAR Four
Run Code Online (Sandbox Code Playgroud)

所以我只得到最后一个值.我知道这一定是因为我对这个宏设施有一些误解,但我不明白为什么变量中只有最后一个值.我认为这只是最后一次调用它的实际执行或其他东西,但是当我调整代码时:

%let stringvar=;
Data _null_;
  set work.test;
  if AddToStringYN = "Y" then do;
    call symput('stringvar'||strip(value),"&stringvar" || strip(value));
  end;
Run;
Run Code Online (Sandbox Code Playgroud)

然后我确实得到了所有这些:

GLOBAL STRINGVARONE  One
GLOBAL STRINGVARTWO  Two
GLOBAL STRINGVARFOUR  Four
Run Code Online (Sandbox Code Playgroud)

所以我的最后一个猜测是,通过数据步骤,'call symput ...'行实际上被添加到宏处理器中,其中"&stringvar"已经被替换,并且只有在最终语句之后它们全部被执行.
这是一个很好的假设还是有另一种解释?回到最初的问题:是否有一种简单的方法来实现这一目标(拥有所需的变量)?

sas*_*rog 5

以下是我对RunSubmit.com上相同问题的回答.我认为你和@Fabio可能会过度设计解决方案,它根本不需要任何迭代数据步骤代码......

首先,做你想做的事的简单方法是这样的:

proc sql;
  select Value into :StringVar separated by ''
    from work.test
    where AddToStringYN='Y'
    ;
quit;
Run Code Online (Sandbox Code Playgroud)

在这里,您可以使用SAS/MACRO的SQL接口,使用select into语法.您甚至可以添加一个order by子句来获取您正在寻找的特定订单.

其次,因为你已经在一些有关的方式SAS宏工作发生了,你是热衷于了解:在你的第一个例子,在执行代码之前编译器做的第一件事是解决的价值&stringvar,这在点是空的.所以在编译之后,替换了这个标记,你的代码就像SAS一样......

%let stringvar=;
Data _null_;
  set work.test;
  if AddToStringYN = "Y" then do;
    call symput('stringvar',"" || strip(value));
  end;
Run;
Run Code Online (Sandbox Code Playgroud)

...然后SAS继续运行该代码(恰好是有效代码,但是将空字符串连接到某些东西的开头).并且由于数据步骤的工作方式,数据步骤的每次迭代实际上都替换了值StringVar,这就是为什么在数据步骤结束时,它留下了读入的最后一个值.