mirror of
https://github.com/sasjs/core.git
synced 2025-12-10 14:04:36 +00:00
92 lines
2.4 KiB
SAS
92 lines
2.4 KiB
SAS
/**
|
|
@file
|
|
@brief Returns all children from a hierarchy table for a specified parent
|
|
@details Where data stores hierarchies in a simple parent / child mapping,
|
|
it is not always straightforward to extract all the children for a
|
|
particular parent. This problem is known as a recursive self join. This
|
|
macro will extract all the descendents for a parent.
|
|
Usage:
|
|
|
|
data have;
|
|
p=1;c=2;output;
|
|
p=2;c=3;output;
|
|
p=2;c=4;output;
|
|
p=3;c=5;output;
|
|
p=6;c=7;output;
|
|
p=8;c=9;output;
|
|
run;
|
|
|
|
%mp_recursivejoin(base_ds=have
|
|
,outds=want
|
|
,matchval=1
|
|
,parentvar=p
|
|
,childvar=c
|
|
)
|
|
|
|
@param [in] base_ds= base table containing hierarchy (not modified)
|
|
@param [out] outds= the output dataset to create with the generated hierarchy
|
|
@param [in] matchval= the ultimate parent from which to filter
|
|
@param [in] parentvar= name of the parent variable
|
|
@param [in] childvar= () name of the child variable (should be same type as
|
|
parent)
|
|
@param [in] mdebug= set to 1 to prevent temp tables being dropped
|
|
|
|
|
|
@returns outds contains the following variables:
|
|
- level (0 = top level)
|
|
- &parentvar
|
|
- &childvar (null if none found)
|
|
|
|
@version 9.2
|
|
@author Allan Bowe
|
|
|
|
**/
|
|
|
|
%macro mp_recursivejoin(base_ds=
|
|
,outds=
|
|
,matchval=
|
|
,parentvar=
|
|
,childvar=
|
|
,iter= /* reserved for internal / recursive use by the macro itself */
|
|
,maxiter=500 /* avoid infinite loop */
|
|
,mDebug=0);
|
|
|
|
%if &iter= %then %do;
|
|
proc sql;
|
|
create table &outds as
|
|
select 0 as level,&parentvar, &childvar
|
|
from &base_ds
|
|
where &parentvar=&matchval;
|
|
%if &sqlobs.=0 %then %do;
|
|
%put NOTE: &sysmacroname: No match for &parentvar=&matchval;
|
|
%return;
|
|
%end;
|
|
%let iter=1;
|
|
%end;
|
|
%else %if &iter>&maxiter %then %return;
|
|
|
|
proc sql;
|
|
create table _data_ as
|
|
select &iter as level
|
|
,curr.&childvar as &parentvar
|
|
,base_ds.&childvar as &childvar
|
|
from &outds curr
|
|
left join &base_ds base_ds
|
|
on curr.&childvar=base_ds.&parentvar
|
|
where curr.level=%eval(&iter.-1)
|
|
& curr.&childvar is not null;
|
|
%local append_ds; %let append_ds=&syslast;
|
|
%local obs; %let obs=&sqlobs;
|
|
insert into &outds select distinct * from &append_ds;
|
|
%if &mdebug=0 %then drop table &append_ds;;
|
|
|
|
%if &obs %then %do;
|
|
%mp_recursivejoin(iter=%eval(&iter.+1)
|
|
,outds=&outds,parentvar=&parentvar
|
|
,childvar=&childvar
|
|
,base_ds=&base_ds
|
|
)
|
|
%end;
|
|
|
|
%mend mp_recursivejoin;
|