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

Proper way to write recursive code in SAS

我正在使用两个 table。

先有RK、ID、姓名等基本信息

second table 创建层次结构并将列作为 RK 和 Parent_RK

我想在他的完整层次结构下获取一条记录的所有 children。

我的密码是

%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

第三个周期

莫11386没有孩子

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

现在系统将回到第二个循环

MO= 11387 没有孩子

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

现在系统将回到第一个循环

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

我们可以在 do 循环中做多线程而不是首先执行 child 他应该首先将所有 children 发送到宏然后对他们的孩子做同样的事情。

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

该宏的主要修复方法是确保将宏变量定义为局部变量。这对于可能被其他宏调用的任何宏都很重要,以防止它覆盖已经存在的具有这些名称的宏变量。显然递归调用宏时肯定存在宏变量名冲突的可能性。

%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;