在 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;
我正在使用两个 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;