<?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: Assign first ID based on Prior ID values in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756378#M238776</link>
    <description>&lt;P&gt;If there are no circular references, then this task can be simplified:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want;
  set have;
  if _n_=1 then do;
    declare hash h (dataset:'have (where=(not missing (p_id)))');
     h.definekey('id');
     h.definedata('p_id');
     h.definedone();
  end;
  if not missing(p_id) then do until(h.find()^=0);
    id=p_id;
  end;
  need=p_id;
  set have;
run;
    &lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The &lt;EM&gt;&lt;STRONG&gt;h.find()&lt;/STRONG&gt;&lt;/EM&gt; method for the hash object &lt;EM&gt;&lt;STRONG&gt;h&lt;/STRONG&gt;&lt;/EM&gt; is a way to step from ID to P_ID, then to the P_ID of the P_ID, etc., until no further P_ID can be found.&amp;nbsp; The only problem is that the loop using the &lt;EM&gt;&lt;STRONG&gt;h.find()&lt;/STRONG&gt;&lt;/EM&gt; method, keeps modifying&amp;nbsp; P_ID and ID until the find failure, losing the original ID and P_ID..&amp;nbsp; But this is enough to get the NEED value.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Then just re-read the original observation (via the second SET statement) to restore the original ID and P_ID values.&amp;nbsp; The point is that the two SET statement are a way to read each observation twice, once before establishing NEED, and once after.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Additional material below:&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;PS: Here's what the program would look like if you add a circularity check.&amp;nbsp; It establishes an &lt;EM&gt;&lt;STRONG&gt;_orig_id=id&lt;/STRONG&gt;&lt;/EM&gt;&amp;nbsp; and adds a test for "&lt;EM&gt;&lt;STRONG&gt;id=_orig_id&lt;/STRONG&gt;&lt;/EM&gt;" in the &lt;EM&gt;&lt;STRONG&gt;UNTIL&lt;/STRONG&gt;&lt;/EM&gt; clause:&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want (drop=_:);
  set have;
  if _n_=1 then do;
    declare hash h (dataset:'have (where=(not missing (p_id)))');
     h.definekey('id');
     h.definedata('p_id');
     h.definedone();
  end;

  _orig_id=id;     /* For circularity check */

  if not missing(p_id) then do until(h.find()^=0 or id=_orig_id);
    id=p_id;
  end;
  need=p_id;
  set have;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;However, this code is NOT robust against having a given P_ID show up twice, when at least one instance is in a circular reference.&amp;nbsp; &amp;nbsp; Although multiple instances of a given P_ID in which none of them occur is a circle does not present a problem.&lt;/P&gt;</description>
    <pubDate>Mon, 26 Jul 2021 03:42:45 GMT</pubDate>
    <dc:creator>mkeintz</dc:creator>
    <dc:date>2021-07-26T03:42:45Z</dc:date>
    <item>
      <title>Assign first ID based on Prior ID values</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756342#M238751</link>
      <description>&lt;P&gt;Hello Experts,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Hope all are doing fine. Please apologize to bother you with my question.&lt;/P&gt;&lt;P&gt;I am trying to assign the initial ID to the other ID rows based on Prior ID column. Can you please help on this to figure the way to do it.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have&lt;/P&gt;&lt;P&gt;&lt;BR /&gt;data have;&lt;BR /&gt;input ID $ p_id $ ;&lt;BR /&gt;datalines;&lt;BR /&gt;006 .&lt;BR /&gt;007 006&lt;BR /&gt;008 .&lt;BR /&gt;009 .&lt;BR /&gt;010 007&lt;BR /&gt;011 010&lt;BR /&gt;;&lt;BR /&gt;run;&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Capture.PNG" style="width: 210px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/61661iF5EE2A5DA9F1F1FF/image-size/large?v=v2&amp;amp;px=999" role="button" title="Capture.PNG" alt="Capture.PNG" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I want&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Capture.PNG" style="width: 304px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/61660i81C547974D2FBDAB/image-size/large?v=v2&amp;amp;px=999" role="button" title="Capture.PNG" alt="Capture.PNG" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Here, I am trying to create the 'NEED' column with first ID number value based on P_ID. If you see row#2 has P_ID as '006' , since I have record with ID = '006' so I need to get NEED = '006' for that record. Row # 5 has P_ID = '007' which has inital P_ID is '006', so I want '006' in NEED column for rows # 5. Likewise, For Row # 6, based on all previous P_ID values, we should get NEED = '006' for that column. Can you please help on this.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thanks all and Have a great day.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 23 Jul 2021 23:44:36 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756342#M238751</guid>
      <dc:creator>Mr_sassy_sug</dc:creator>
      <dc:date>2021-07-23T23:44:36Z</dc:date>
    </item>
    <item>
      <title>Re: Assign first ID based on Prior ID values</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756344#M238753</link>
      <description>&lt;P&gt;So you want to reference the original parent ID? And I suppose you have more than one&amp;nbsp;original parent ID?&lt;/P&gt;</description>
      <pubDate>Sat, 24 Jul 2021 00:48:00 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756344#M238753</guid>
      <dc:creator>ChrisNZ</dc:creator>
      <dc:date>2021-07-24T00:48:00Z</dc:date>
    </item>
    <item>
      <title>Re: Assign first ID based on Prior ID values</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756350#M238757</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/319712"&gt;@Mr_sassy_sug&lt;/a&gt;&amp;nbsp;Something like below should do the job.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
  input ID $ p_id $;
  datalines;
006 .
007 006
008 .
009 .
010 007
011 010
012 008
013 012
014 015
015 014
;

proc sql;
  create view hierarchy as
    select
      id as _child,
      p_id as _parent
    from have
    where p_id is not missing
    ;
quit;

%let max_depth=99;
data want(drop=_:);
  if _n_=1 then
    do;
      if 0 then set hierarchy;
      dcl hash h1(dataset:'hierarchy');
      h1.defineKey('_child');
      h1.defineData('_child','_parent');
      h1.defineDone();
    end;
  call missing(_child,_parent);

  set have;

  if not missing(p_id) then
    do; 
      _parent=p_id;
      do _i=1 to &amp;amp;max_depth until(h1.find(key:_parent) ne 0);
      end;
      need=_parent;
      /* investigate data if _i &amp;gt; &amp;amp;max_depth */
      if _i&amp;gt;&amp;amp;max_depth then circular_reference_flg=1;
    end;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="Patrick_0-1627091756087.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/61664i8B165AFC90942628/image-size/medium?v=v2&amp;amp;px=400" role="button" title="Patrick_0-1627091756087.png" alt="Patrick_0-1627091756087.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 24 Jul 2021 01:56:07 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756350#M238757</guid>
      <dc:creator>Patrick</dc:creator>
      <dc:date>2021-07-24T01:56:07Z</dc:date>
    </item>
    <item>
      <title>Re: Assign first ID based on Prior ID values</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756378#M238776</link>
      <description>&lt;P&gt;If there are no circular references, then this task can be simplified:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want;
  set have;
  if _n_=1 then do;
    declare hash h (dataset:'have (where=(not missing (p_id)))');
     h.definekey('id');
     h.definedata('p_id');
     h.definedone();
  end;
  if not missing(p_id) then do until(h.find()^=0);
    id=p_id;
  end;
  need=p_id;
  set have;
run;
    &lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The &lt;EM&gt;&lt;STRONG&gt;h.find()&lt;/STRONG&gt;&lt;/EM&gt; method for the hash object &lt;EM&gt;&lt;STRONG&gt;h&lt;/STRONG&gt;&lt;/EM&gt; is a way to step from ID to P_ID, then to the P_ID of the P_ID, etc., until no further P_ID can be found.&amp;nbsp; The only problem is that the loop using the &lt;EM&gt;&lt;STRONG&gt;h.find()&lt;/STRONG&gt;&lt;/EM&gt; method, keeps modifying&amp;nbsp; P_ID and ID until the find failure, losing the original ID and P_ID..&amp;nbsp; But this is enough to get the NEED value.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Then just re-read the original observation (via the second SET statement) to restore the original ID and P_ID values.&amp;nbsp; The point is that the two SET statement are a way to read each observation twice, once before establishing NEED, and once after.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Additional material below:&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;PS: Here's what the program would look like if you add a circularity check.&amp;nbsp; It establishes an &lt;EM&gt;&lt;STRONG&gt;_orig_id=id&lt;/STRONG&gt;&lt;/EM&gt;&amp;nbsp; and adds a test for "&lt;EM&gt;&lt;STRONG&gt;id=_orig_id&lt;/STRONG&gt;&lt;/EM&gt;" in the &lt;EM&gt;&lt;STRONG&gt;UNTIL&lt;/STRONG&gt;&lt;/EM&gt; clause:&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want (drop=_:);
  set have;
  if _n_=1 then do;
    declare hash h (dataset:'have (where=(not missing (p_id)))');
     h.definekey('id');
     h.definedata('p_id');
     h.definedone();
  end;

  _orig_id=id;     /* For circularity check */

  if not missing(p_id) then do until(h.find()^=0 or id=_orig_id);
    id=p_id;
  end;
  need=p_id;
  set have;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;However, this code is NOT robust against having a given P_ID show up twice, when at least one instance is in a circular reference.&amp;nbsp; &amp;nbsp; Although multiple instances of a given P_ID in which none of them occur is a circle does not present a problem.&lt;/P&gt;</description>
      <pubDate>Mon, 26 Jul 2021 03:42:45 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756378#M238776</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2021-07-26T03:42:45Z</dc:date>
    </item>
    <item>
      <title>Re: Assign first ID based on Prior ID values</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756433#M238817</link>
      <description>&lt;P&gt;Yes, that is correct&lt;/P&gt;</description>
      <pubDate>Sat, 24 Jul 2021 23:06:26 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756433#M238817</guid>
      <dc:creator>Mr_sassy_sug</dc:creator>
      <dc:date>2021-07-24T23:06:26Z</dc:date>
    </item>
    <item>
      <title>Re: Assign first ID based on Prior ID values</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756434#M238818</link>
      <description>&lt;P&gt;Thank you so much, this is really helpful and it works to my situation.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thank you so much again.&lt;/P&gt;</description>
      <pubDate>Sat, 24 Jul 2021 23:07:17 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756434#M238818</guid>
      <dc:creator>Mr_sassy_sug</dc:creator>
      <dc:date>2021-07-24T23:07:17Z</dc:date>
    </item>
    <item>
      <title>Re: Assign first ID based on Prior ID values</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756435#M238819</link>
      <description>&lt;P&gt;Thank you so much and this is really simple and straight to the point. I really appreciate your help.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thanks again for your valuable on this&lt;/P&gt;</description>
      <pubDate>Sat, 24 Jul 2021 23:08:08 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756435#M238819</guid>
      <dc:creator>Mr_sassy_sug</dc:creator>
      <dc:date>2021-07-24T23:08:08Z</dc:date>
    </item>
    <item>
      <title>Re: Assign first ID based on Prior ID values</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756452#M238828</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/31461"&gt;@mkeintz&lt;/a&gt;&amp;nbsp;This lookup will in case of a match overwrite p_id in the base table with p_id from the hash. This could lead to a wrong outcome in case of DQ issues in the base table.&lt;/P&gt;</description>
      <pubDate>Sun, 25 Jul 2021 05:32:59 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756452#M238828</guid>
      <dc:creator>Patrick</dc:creator>
      <dc:date>2021-07-25T05:32:59Z</dc:date>
    </item>
    <item>
      <title>Re: Assign first ID based on Prior ID values</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756525#M238872</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/12447"&gt;@Patrick&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/31461"&gt;@mkeintz&lt;/a&gt;&amp;nbsp;This lookup will in case of a match overwrite p_id in the base table with p_id from the hash. This could lead to a wrong outcome in case of DQ issues in the base table.&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Yes.&amp;nbsp; I believe that issue is addressed by the second SET statement, that follows the calculation of NEED.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;"DQ issues".&amp;nbsp; Is that "Data Quality"?&amp;nbsp; I qualified my code offering as not suitable for data having circular references (although a check for circularity could be easily put in).&amp;nbsp; Is there something else I missed (won't be the first time)?&lt;/P&gt;</description>
      <pubDate>Sun, 25 Jul 2021 18:26:59 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Assign-first-ID-based-on-Prior-ID-values/m-p/756525#M238872</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2021-07-25T18:26:59Z</dc:date>
    </item>
  </channel>
</rss>

