在SAS中编写递归代码的正确方法

时间:2018-07-12 11:55:34

标签: sql sas sas-macro

我有两个要使用的表。

首先具有RK,ID和名称等基本信息

第二张表创建层次结构,并具有RK和Parent_RK列

我想让唱片的所有子级都归他所有。

我的代码是

%let _MO = 11382;

proc sql noprint;
create table management(
rk int,
ID varchar(4000),
Name varchar(4000)
);
quit;

%macro recursive(MO);

%put &MO;

proc sql noprint;
insert into management
select distinct Par.management_org_rk, Mo.management_org_id,Mo.Organization_nm
from Sasoprsk.Management_org_assoc_l par
inner join Sasoprsk.Management_org_l Mo on Mo.management_org_rk = par.management_org_rk
where par.management_org_rk = &MO;

select distinct management_org_rk
into: MO_List separated by "|"
from Sasoprsk.Management_org_assoc_l
where Parent_management_org_rk = &MO
and MANAGEMENT_ORG_ASSOC_TYPE_CD = 'DEF';

select count(distinct management_org_rk)
into: count
from Sasoprsk.Management_org_assoc_l
where Parent_management_org_rk = &MO
and MANAGEMENT_ORG_ASSOC_TYPE_CD = 'DEF';
quit;

%put &MO_List;
%put &count;

%if &count ne 0 %then 
%do i=1 %to &count;
    %let Child=%scan(%bquote(&MO_List), %bquote(&i) ,%str(|));
    %recursive(&Child);
    %put &i;
%end;

%mend;

%recursive(&_MO);

空运行

第一个周期

假设MO 11382有3个孩子

MO_List = 11383|11384|1138
count = 3
child = 11383

第二周期

MO 11383有2个孩子

MO_List = 11386|11387
count =2
child = 11386

第三周期

Mo 11386没有孩子

MO_List =11386|11387;
count = 0;
i=1;

现在系统将返回第二个周期

MO = 11387没有孩子

MO_List =11386|11387;
count = 0;
i=2;

现在系统将返回到第一个周期

由于MO_List已更新,因此无法继续。 请建议我一种更好的方法来获得MO的所有子代。在服务器中,有十个层次结构,所以我不能硬编码。

我们可以在do循环中执行多线程吗,而不是与第一个孩子执行,他应该先将所有的孩子发送到宏,然后再对他们的孩子执行相同的操作。

层次结构就像具有多个节点的树。

1 个答案:

答案 0 :(得分:0)

该宏的主要解决方法是确保将宏变量定义为局部变量。这对于其他宏可能调用以防止其覆盖那些名称已存在的宏变量的宏非常重要。显然,递归调用宏时肯定存在宏变量名称冲突的可能性。

%macro recursive(MO);
  %local mo_list count i ;
  ...

请注意,您还可以消除重复查询以计算写入MO_LIST的值的数量。 SAS已经为您算了。

select distinct management_org_rk
  into :MO_List separated by "|"
from Sasoprsk.Management_org_assoc_l
where Parent_management_org_rk = &MO
  and MANAGEMENT_ORG_ASSOC_TYPE_CD = 'DEF'
;
%let count=&sqlobs;
相关问题