SAS宏 - 创建一个正在运行的宏作为另一组宏的串联

时间:2014-12-12 11:58:18

标签: sas sas-macro

我有一个宏观相关的问题,我正在努力发展和理解。任何解决这个问题的指针都将非常感激: - )

下面有类似的内容:

我有'n'[变量]数量的宏变量'Key'解析为

& Key1 = 1& Key = 2& Key3 = 3 ............... .. .......... &安培; Keyn = N

我想创建一个自动运行的宏'Masterkey',类似于

& Masterkey = 1& Masterkey2 = 12& Masterkey = 123 .......... .........。

即。 &安培; MasterKeyN = 123 ...... ...... N

我怎样才能创建'& MasterkeyN',其中N未固定,因为可以根据[1-n]个键的每组情况进行变量?

非常感谢。

纳德

2 个答案:

答案 0 :(得分:1)

我认为这可能不是一种有用的技巧,但无论如何我都会回答它。

我还假设&Key1..n可能包含存储在其中的数字以外的值,并且您希望将这些值收集到&MasterKey1..n变量中。

您需要做的是使用嵌套循环,并了解宏变量如何解决。

%let key1=A;
%let key2=B;
%let key3=C;

%global MasterKey1 MasterKey2 MasterKey3; *so they work outside of the macro;

%macro create_master(numKeys=);
  %do master=1 %to &numKeys;              *Outer loop for the MasterKeys we want to make;
    %let temp=;
    %do keyiter = 1 %to &master;          *Inner loop for the keys that fall into the MasterKey;
      %let temp = &temp.&&Key&keyiter.;   *&& delays macro variable resolution one time.;
    %end;
    %let MasterKey&master.=&temp.;
  %end;
%mend create_master;
%create_master(numkeys=3);

%put &=MasterKey1 &=MasterKey2 &=MasterKey3;

这里的魔力是&&。基本上,在宏变量解析期间,您一次只处理一个或两个。如果它有助于在循环中放置一些%put语句来查看它是如何工作的。

首先,让我们跳到最后。在此次迭代中,&temp=AB &Keyiter=3&Key3=C

0. &temp.&&Key&keyiter
1. AB&Key3
2. ABC

因此,从0到1,解析器会看到&temp.,表示一个变量结束的句点,所以它会查找那个:&temp.=AB并用AB替换它。然后它会看到两个&,并用一个&替换它们,但不会尝试用它们解决任何问题。然后它看到Key,那里没有&符号,所以没什么可做的。然后它会看到&keyiter,好吧,用3替换它。

然后从1到2,它看到AB,忽略它应该。然后它看到&Key3(两个&符号变成了一个不要忘记),现在它知道将其解析为C,它确实如此 - 因此ABC。

答案 1 :(得分:0)

非常感谢大家提供的有用评论和解决方案。是的,绝对可以通过多种方式在SAS中提供解决方案。我可能从一个角度着手接近这个问题。无论如何,我现在能够解决这个问题。 以下是有关问题的简要概述和“以下解决方案:

我有许多客户和交易表。目标是根据匹配类型+进程密钥和匹配键匹配/连接两个表(匹配键是表中的字段。 关于匹配的说明由类似于底部的表格给出。 我正在尝试构建一个宏,其中包含基于某些匹配类型和进程密钥的连接指令,例如:对于匹配类型= Profile和Process key = 3,我想创建一个包含字符串的宏(下面的链接),然后可以将其输入proc sql命令: ]

Table1.Name=Table2.Name 
And Table1.Address=Table2.Address 

]

我根据匹配类型和进程键为每个匹配键创建了一个宏,并希望在第二个和后续键之前添加键[带'和'文本]的动态串联。我遇到的问题是,对于任何给定的匹配类型和进程密钥,没有固定数量的匹配键。

Matching_Type Process_Key Matching_Keys 
Profile 1 Name 
Profile 1 Address 
Profile 1 Gender 
Market 1 Name 
Market 1 Income 
Profile 2 Name 
Profile 2 Address 
Profile 2 Gender 
Profile 2 DoB 
Profile 2 Phone_Number 
Market 2 Name 
Market 2 Address 
Market 2 Gender 
Market 2 Income 
Market 2 Transaction_Amount 
Market 2 Credit_Card_Number 
Profile 3 Name 
Profile 3 Address 

解决方案:

%macro test; 
proc sql noprint; 
select left(put(count(distinct matching_type||left(put(process_key,8.))),8.)) into :num 
from test; 
select distinct matching_type, process_key into :matchkey1 - :matchkey&num, :processkey1-:processkey&num 
from test; 
%do i=1 %to # 
%global &&matchkey&i&&processkey&i; 
select 'table1.'||trim(matching_keys)||' = table2.'||trim(matching_keys) into :&&matchkey&i&&processkey&i separated by ' and ' 
from test 
where matching_type="&&matchkey&i" and process_key=&&processkey&i; 
%end; 
quit; 
%mend; 

options mprint; 
%test; 

%put _user_; 

非常感谢大家。