<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Creating new variables by comparing values within same dataset in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610840#M177961</link>
    <description>&lt;P&gt;Thank you Erik!&amp;nbsp; This works perfectly for the results I need.&amp;nbsp; You made my day.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Tue, 10 Dec 2019 21:20:25 GMT</pubDate>
    <dc:creator>i_r</dc:creator>
    <dc:date>2019-12-10T21:20:25Z</dc:date>
    <item>
      <title>Creating new variables by comparing values within same dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610567#M177814</link>
      <description>&lt;P&gt;Hi.&amp;nbsp; I’m reading a file with only two variables, id1 and id2.&amp;nbsp; The file has parent id's that can split into multiple child id's and a child id can further split or produce another child id.&amp;nbsp; There is no link on these records other than id2 can appear as id1 in a subsequent record.&amp;nbsp; I would like to end up with a flattened dataset as the example below.&amp;nbsp; Can you suggest the best way to get this accomplished?&amp;nbsp; Thanks in advance.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data have;&lt;BR /&gt;infile datalines delimiter=',';&lt;BR /&gt;input id1:$16. id2:$16.;&lt;BR /&gt;datalines;&lt;BR /&gt;1909307070100103,1909307070103065&lt;BR /&gt;1909307070100103,1909307070103064&lt;BR /&gt;1909307070100171,1909307070103061&lt;BR /&gt;1909307070100171,1909307070103060&lt;BR /&gt;1909307070100196,1909307070103088&lt;BR /&gt;1909307070100196,1909307070103089&lt;BR /&gt;1909307070100196,1909307070103090&lt;BR /&gt;1909307070100196,1909307070103091&lt;BR /&gt;1909307070100201,1909307070103106&lt;BR /&gt;1909307070103061,1909307070103117&lt;BR /&gt;1909307070103062,1909307070103105&lt;BR /&gt;1909307070103065,1909307070103087&lt;BR /&gt;1909307070103067,1909307070103104&lt;BR /&gt;;&lt;BR /&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Want&lt;/P&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; id1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; id2&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; id3&lt;/P&gt;&lt;P&gt;1909307070100103&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103065&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103087&lt;/P&gt;&lt;P&gt;1909307070100103&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103064&lt;/P&gt;&lt;P&gt;1909307070100171&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103061&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103117&lt;/P&gt;&lt;P&gt;1909307070100171&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103060&lt;/P&gt;&lt;P&gt;1909307070100196&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103088&lt;/P&gt;&lt;P&gt;1909307070100196&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103089&lt;/P&gt;&lt;P&gt;1909307070100196&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103090&lt;/P&gt;&lt;P&gt;1909307070100196&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103091&lt;/P&gt;&lt;P&gt;1909307070100201&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103106&lt;/P&gt;&lt;P&gt;1909307070103062&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103105&lt;/P&gt;&lt;P&gt;1909307070103067&amp;nbsp;&amp;nbsp;&amp;nbsp; 1909307070103104&lt;/P&gt;</description>
      <pubDate>Mon, 09 Dec 2019 21:51:05 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610567#M177814</guid>
      <dc:creator>i_r</dc:creator>
      <dc:date>2019-12-09T21:51:05Z</dc:date>
    </item>
    <item>
      <title>Re: Creating new variables by comparing values within same dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610624#M177844</link>
      <description>&lt;P&gt;I see you stop at ID3, so I assume that no record can have both a parent record and a child record.&amp;nbsp; If so, then the program below will work.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;One note: to me the key phrase in your request is "&lt;SPAN style="display: inline !important; float: none; background-color: #ffffff; color: #333333; font-family: 'HelevticaNeue-light','Helvetica Neue',Helvetica,Arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; line-height: 150%; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;"&gt;id2 can appear as id1 &lt;EM&gt;&lt;STRONG&gt;in a subsequent record&lt;/STRONG&gt;&lt;/EM&gt;&lt;/SPAN&gt;". &amp;nbsp; This means that if you link an ID2 to some upcoming ID1, then when that ID1 is encountered you can skip outputting that record:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
  infile datalines delimiter=',';
  input id1:$16. id2:$16.;
datalines;
1909307070100103,1909307070103065
1909307070100103,1909307070103064
1909307070100171,1909307070103061
1909307070100171,1909307070103060
1909307070100196,1909307070103088
1909307070100196,1909307070103089
1909307070100196,1909307070103090
1909307070100196,1909307070103091
1909307070100201,1909307070103106
1909307070103061,1909307070103117
1909307070103062,1909307070103105
1909307070103065,1909307070103087
1909307070103067,1909307070103104
run;

data want (drop=_:);
 merge have have (obs=0 rename=(id1=_idkey id2=id3));
 if _n_=1 then do;
    declare hash lookups(dataset:'have (rename=(id1=_idkey id2=id3))');
      lookups.definekey('_idkey');
      lookups.definedata(all:'Y');
      lookups.definedone();
    declare hash already_found ();
      already_found.definekey('_idkey');
      already_found.definedone();
 end;

 /*If child id found, add _IDKEY (=id2) to the hash of found id's */
 if lookups.find(key:id2)=0 then already_found.add();   

 /* Use "subsettinng IF" to filter only records whose ID1 was not previously found as a child */
 if already_found.find(key:id1)^=0;  
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;OL&gt;
&lt;LI&gt;Thank you for generating a working DATA HAVE step.&lt;/LI&gt;
&lt;LI&gt;This program sets up a LOOKUP hash, containing all the data from HAVE. It is keyed on ID1 (renamed as _IDKEY in the hash.&lt;/LI&gt;
&lt;LI&gt;For every incoming record, the ID2 value is searched via the FIND method against all those _IDKEYs. If one is found, then ID3 is will have been successfully retrieved.&lt;/LI&gt;
&lt;LI&gt;I&lt;SPAN style="display: inline !important; float: none; background-color: #ffffff; color: #333333; cursor: text; font-family: 'HelevticaNeue-light','Helvetica Neue',Helvetica,Arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;"&gt;f the FIND was successful (lookups.find(key:id2)=0),then the ID2 value is put in the already_found hash.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN style="display: inline !important; float: none; background-color: #ffffff; color: #333333; cursor: text; font-family: 'HelevticaNeue-light','Helvetica Neue',Helvetica,Arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;"&gt;Any observation whose ID1 is in already_found,will not be output.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;&lt;SPAN style="display: inline !important; float: none; background-color: #ffffff; color: #333333; cursor: text; font-family: 'HelevticaNeue-light','Helvetica Neue',Helvetica,Arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;"&gt;The MERGE statement has HAVE a 2nd time with "obs=0". This forces SAS to set _IDKEY and ID3 (in the rename parameter) to be automatically reset to missing with each iteration of the data step.&lt;/SPAN&gt;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;The only problem with this is that it works only when a child has only 1 child of its own.&amp;nbsp; It would not work with the data below, which has the record &lt;SPAN style="display: inline !important; float: none; background-color: #ffffff; color: #333333; cursor: text; font-family: 'HelevticaNeue-light','Helvetica Neue',Helvetica,Arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;"&gt;4444444444444444,&lt;/SPAN&gt;5555555555555555 is followed by the two records&lt;/P&gt;
&lt;P&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; 5555555555555555,6666666666666666 and&lt;/P&gt;
&lt;P&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; 5555555555555555,7777777777777777.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Presumable you would want&amp;nbsp; output containing&lt;/P&gt;
&lt;P style="color: #333333; font-family: &amp;amp;quot; helevticaneue-light&amp;amp;quot;,&amp;amp;quot;helvetica neue&amp;amp;quot;,helvetica,arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px; padding: 0px; margin: 0px;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;SPAN style="display: inline !important; float: none; background-color: #ffffff; color: #333333; cursor: text; font-family: 'HelevticaNeue-light','Helvetica Neue',Helvetica,Arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;"&gt;4444444444444444,&lt;/SPAN&gt;5555555555555555,6666666666666666 and&lt;/P&gt;
&lt;P style="color: #333333; font-family: &amp;amp;quot; helevticaneue-light&amp;amp;quot;,&amp;amp;quot;helvetica neue&amp;amp;quot;,helvetica,arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px; padding: 0px; margin: 0px;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;SPAN style="display: inline !important; float: none; background-color: #ffffff; color: #333333; cursor: text; font-family: 'HelevticaNeue-light','Helvetica Neue',Helvetica,Arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px;"&gt;4444444444444444,&lt;/SPAN&gt;5555555555555555,7777777777777777.&lt;/P&gt;
&lt;P style="color: #333333; font-family: &amp;amp;quot; helevticaneue-light&amp;amp;quot;,&amp;amp;quot;helvetica neue&amp;amp;quot;,helvetica,arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px; padding: 0px; margin: 0px;"&gt;but the above would not capture the 2nd grandchild.&lt;/P&gt;
&lt;P style="color: #333333; font-family: &amp;amp;quot; helevticaneue-light&amp;amp;quot;,&amp;amp;quot;helvetica neue&amp;amp;quot;,helvetica,arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px; padding: 0px; margin: 0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P style="color: #333333; font-family: &amp;amp;quot; helevticaneue-light&amp;amp;quot;,&amp;amp;quot;helvetica neue&amp;amp;quot;,helvetica,arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px; padding: 0px; margin: 0px;"&gt;To accommodate, you can use:&lt;/P&gt;
&lt;P style="color: #333333; font-family: &amp;amp;quot; helevticaneue-light&amp;amp;quot;,&amp;amp;quot;helvetica neue&amp;amp;quot;,helvetica,arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px; padding: 0px; margin: 0px;"&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
  infile datalines delimiter=',';
  input id1:$16. id2:$16.;
datalines;
1909307070100103,1909307070103065
1909307070100103,1909307070103064
1909307070100171,1909307070103061
1909307070100171,1909307070103060
1909307070100196,1909307070103088
1909307070100196,1909307070103089
1909307070100196,1909307070103090
1909307070100196,1909307070103091
1909307070100201,1909307070103106
1909307070103061,1909307070103117
1909307070103062,1909307070103105
1909307070103065,1909307070103087
1909307070103067,1909307070103104
4444444444444444,5555555555555555
5555555555555555,6666666666666666
5555555555555555,7777777777777777
run;
data want (drop=_:);
 merge have have (obs=0 rename=(id1=_idkey id2=id3));
 if _n_=1 then do;
    declare hash lookups(dataset:'have (rename=(id1=_idkey id2=id3))',multidata:'Y');
      lookups.definekey('_idkey');
      lookups.definedata(all:'Y');
      lookups.definedone();
    declare hash already_found ();
      already_found.definekey('_idkey');
      already_found.definedone();
 end;

 /*If child id found in LOOKUPS, add _IDKEY (=id2) to the hash of found id's */
 if lookups.find(key:id2)=0 then do;
   already_found.add();
   do until (lookups.find_next()^=0);
     output;
   end;
 end;
 /* Output a record if its ID1 was not previously found as a child */
 else if already_found.find(key:id1)^=0 then output;
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P style="color: #333333; font-family: &amp;amp;quot; helevticaneue-light&amp;amp;quot;,&amp;amp;quot;helvetica neue&amp;amp;quot;,helvetica,arial,sans-serif; font-size: 14px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; -webkit-text-stroke-width: 0px; white-space: normal; word-spacing: 0px; padding: 0px; margin: 0px;"&gt;This changes the LOOKUPS hash to "multidata:'Y'", which allows the hash to contain multiple dataitems (think multiple rows) with tied key values. That in turn allows the "find_next" method to traverse all the tied key dataitems.&lt;/P&gt;</description>
      <pubDate>Tue, 10 Dec 2019 06:54:12 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610624#M177844</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2019-12-10T06:54:12Z</dc:date>
    </item>
    <item>
      <title>Re: Creating new variables by comparing values within same dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610644#M177855</link>
      <description>&lt;P&gt;SQL is probably the simplest:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql;
  create table want as select
    parent.id1,parent.id2,child.id2 as id3
  from have parent left join have child on parent.id2=child.id1
  where parent.id1 not in(select id2 from have);
quit;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;But you should consider a couple of questions:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;What if there are branches deeper than 1 (an id2 points to a record, and the id2 in that record points to yet another record)? Should you then have an id4 variable?&lt;/LI&gt;
&lt;LI&gt;What do you want if an id2 value points to more than one other record? In the solution shown here, you will get all the combinations, but is that what you want?&lt;/LI&gt;
&lt;/OL&gt;</description>
      <pubDate>Tue, 10 Dec 2019 08:38:24 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610644#M177855</guid>
      <dc:creator>s_lassen</dc:creator>
      <dc:date>2019-12-10T08:38:24Z</dc:date>
    </item>
    <item>
      <title>Re: Creating new variables by comparing values within same dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610757#M177915</link>
      <description>&lt;P&gt;Thanks for your response.&amp;nbsp; There will be branches deeper than my example shows and there could be id4, id5, etc.&amp;nbsp; I would want every unique branch created.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 10 Dec 2019 15:50:04 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610757#M177915</guid>
      <dc:creator>i_r</dc:creator>
      <dc:date>2019-12-10T15:50:04Z</dc:date>
    </item>
    <item>
      <title>Re: Creating new variables by comparing values within same dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610791#M177933</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/302603"&gt;@i_r&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You can do it with a series of Proc SQL steps. I have made an example and also shown how the SQL step coud be placed in a macro loop, so the code will handle an unknown number of levels in the tree structure.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;* Test data - a 4. level is included as last record for test putposes;
data have;
  infile datalines delimiter=',';
  input id1:$16. id2:$16.;
datalines;
1909307070100103,1909307070103065
1909307070100103,1909307070103064
1909307070100171,1909307070103061
1909307070100171,1909307070103060
1909307070100196,1909307070103088
1909307070100196,1909307070103089
1909307070100196,1909307070103090
1909307070100196,1909307070103091
1909307070100201,1909307070103106
1909307070103061,1909307070103117
1909307070103062,1909307070103105
1909307070103065,1909307070103087
1909307070103067,1909307070103104
1909307070103087,1909307070103099
run;

/*-----------------------------------------------------------------------
Bulding the tree with a SQL step for each level - steps are manually added
until last level is reached, i.e. no more childs are added as a next
level.
-----------------------------------------------------------------------*/

proc sql noprint;
	create table n1 as 
		select distinct id1 as n1 from have
		where id2 not in (select id1 from have);
quit;

proc sql;
	create table n2 as 
		select a.n1, b.id2 as n2
		from n1 as a left join have as b
		on a.n1 = b.id1 ;
quit;

proc sql;
	create table n3 as 
		select a.n1, a.n2, b.id2 as n3
		from n2 as a left join have as b
		on a.n2 = b.id1 ;
quit;

proc sql;
	create table n4 as 
		select a.n1, a.n2, a.n3, b.id2 as n4
		from n3 as a left join have as b
		on a.n3 = b.id1 ;
quit;

proc sql;
	create table n5 as 
		select a.n1, a.n2, a.n3, a.n4, b.id2 as n5
		from n4 as a left join have as b
		on a.n4 = b.id1 ;
quit;


/*-----------------------------------------------------------------------
Same principle, but with a macro loop to repeat SQL step until last level 
is reached, so an unknown number of levels is processed.
-----------------------------------------------------------------------*/

%macro buildtree;

	* Level 1;
	proc sql noprint;
		create table n1 as 
			select distinct id1 as n1 from have
			where id2 not in (select id1 from have);
	quit;

	* Loop and add levels until the tree is exhausted - next level is empty;
	%let i = 0;
	%do %until (&amp;amp;nextfound = 0);
		%let i = %eval(&amp;amp;i+1);
		proc sql noprint;
			create table n%eval(&amp;amp;i+1) as 
				select a.*, b.id2 as n%eval(&amp;amp;i+1)
				from n&amp;amp;i as a left join have as b
				on a.n&amp;amp;i = b.id1 ;

			select count(*) into :nextfound from n%eval(&amp;amp;i+1)
				where n%eval(&amp;amp;i+1) ne ''; 
		quit;
	%end;

	* Keep last data set with a new level found as Want;
	data want; set n&amp;amp;i; run;

	* Drop intermediate data sets;
	proc datasets lib=work nolist;
		delete n:;
	quit;

%mend;
%buildtree;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 10 Dec 2019 18:21:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610791#M177933</guid>
      <dc:creator>ErikLund_Jensen</dc:creator>
      <dc:date>2019-12-10T18:21:11Z</dc:date>
    </item>
    <item>
      <title>Re: Creating new variables by comparing values within same dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610840#M177961</link>
      <description>&lt;P&gt;Thank you Erik!&amp;nbsp; This works perfectly for the results I need.&amp;nbsp; You made my day.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 10 Dec 2019 21:20:25 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Creating-new-variables-by-comparing-values-within-same-dataset/m-p/610840#M177961</guid>
      <dc:creator>i_r</dc:creator>
      <dc:date>2019-12-10T21:20:25Z</dc:date>
    </item>
  </channel>
</rss>

