Macros for SAS Application Developers
https://github.com/sasjs/core
Loading...
Searching...
No Matches
mp_recursivejoin.sas
Go to the documentation of this file.
1/**
2 @file
3 @brief Returns all children from a hierarchy table for a specified parent
4 @details Where data stores hierarchies in a simple parent / child mapping,
5 it is not always straightforward to extract all the children for a
6 particular parent. This problem is known as a recursive self join. This
7 macro will extract all the descendents for a parent.
8 Usage:
9
10 data have;
11 p=1;c=2;output;
12 p=2;c=3;output;
13 p=2;c=4;output;
14 p=3;c=5;output;
15 p=6;c=7;output;
16 p=8;c=9;output;
17 run;
18
19 %mp_recursivejoin(base_ds=have
20 ,outds=want
21 ,matchval=1
22 ,parentvar=p
23 ,childvar=c
24 )
25
26 @param [in] base_ds= base table containing hierarchy (not modified)
27 @param [out] outds= the output dataset to create with the generated hierarchy
28 @param [in] matchval= the ultimate parent from which to filter
29 @param [in] parentvar= name of the parent variable
30 @param [in] childvar= () name of the child variable (should be same type as
31 parent)
32 @param [in] mdebug= set to 1 to prevent temp tables being dropped
33
34
35 @returns outds contains the following variables:
36 - level (0 = top level)
37 - &parentvar
38 - &childvar (null if none found)
39
40 @version 9.2
41 @author Allan Bowe
42
43**/
44
45%macro mp_recursivejoin(base_ds=
46 ,outds=
47 ,matchval=
48 ,parentvar=
49 ,childvar=
50 ,iter= /* reserved for internal / recursive use by the macro itself */
51 ,maxiter=500 /* avoid infinite loop */
52 ,mDebug=0);
53
54%if &iter= %then %do;
55 proc sql;
56 create table &outds as
57 select 0 as level,&parentvar, &childvar
58 from &base_ds
59 where &parentvar=&matchval;
60 %if &sqlobs.=0 %then %do;
61 %put NOTE: &sysmacroname: No match for &parentvar=&matchval;
62 %return;
63 %end;
64 %let iter=1;
65%end;
66%else %if &iter>&maxiter %then %return;
67
68proc sql;
69create table _data_ as
70 select &iter as level
71 ,curr.&childvar as &parentvar
72 ,base_ds.&childvar as &childvar
73 from &outds curr
74 left join &base_ds base_ds
75 on curr.&childvar=base_ds.&parentvar
76 where curr.level=%eval(&iter.-1)
77 & curr.&childvar is not null;
78%local append_ds; %let append_ds=&syslast;
79%local obs; %let obs=&sqlobs;
80insert into &outds select distinct * from &append_ds;
81%if &mdebug=0 %then drop table &append_ds;;
82
83%if &obs %then %do;
84 %mp_recursivejoin(iter=%eval(&iter.+1)
85 ,outds=&outds,parentvar=&parentvar
86 ,childvar=&childvar
87 ,base_ds=&base_ds
88 )
89%end;
90
91%mend mp_recursivejoin;