<?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: Hash Objects | Count changes to a parent ID over time and list history of related child ID's in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868619#M343143</link>
    <description>Have you checked you work library?&lt;BR /&gt;The code does not use proc print.</description>
    <pubDate>Fri, 07 Apr 2023 15:10:06 GMT</pubDate>
    <dc:creator>AhmedAl_Attar</dc:creator>
    <dc:date>2023-04-07T15:10:06Z</dc:date>
    <item>
      <title>Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868081#M342867</link>
      <description>&lt;P&gt;I want to be able to input a table of parent ID's and count the number of times the ID has changed over time and also create a list of the parent ID and all the related children ID's, including the date the child ID's changed.&amp;nbsp; I'm experimenting with the data/ hash objects in the attachment.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The hash objects code does not produce output for “want”. I would like the output to show:&lt;BR /&gt;1). As of the current evaluation date (8/15/10), the # times the parent ID I specified (4) changed &amp;amp; the original ID:&lt;/P&gt;&lt;P&gt;asof | origid | currid&amp;nbsp; | changecount&lt;/P&gt;&lt;P&gt;08/15/2010&amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp;4&amp;nbsp; &amp;nbsp; &amp;nbsp;3&amp;nbsp;&lt;/P&gt;&lt;P&gt;AND&lt;/P&gt;&lt;P&gt;2). The historical series of changes related to the current parent ID (4):&lt;/P&gt;&lt;P&gt;changedate| oldid | newid&lt;BR /&gt;01/01/2010&amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp;2&lt;BR /&gt;07/01/2010&amp;nbsp; &amp;nbsp;2&amp;nbsp; &amp;nbsp;3&lt;BR /&gt;07/10/2010&amp;nbsp; &amp;nbsp;3&amp;nbsp; &amp;nbsp;4&lt;BR /&gt;I'm new to the Community, so please let me know if I should modify this post to make it easier for the Community to evaluate.&amp;nbsp; I could not find the insert SAS code tool, which may have presented better.&lt;/P&gt;</description>
      <pubDate>Tue, 04 Apr 2023 20:37:21 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868081#M342867</guid>
      <dc:creator>bobsas1</dc:creator>
      <dc:date>2023-04-04T20:37:21Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868341#M343016</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/427679"&gt;@bobsas1&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;My approach does not involve Hash Object, but I was interested in this little puzzle.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;
data have;
	attrib oldid newid length=8 changedate informat=mmddyy10. format=mmddyy10.;
	input oldid newid changedate;
	datalines;
1 2 1/1/10
10 11 1/1/10
2 3 7/1/10
3 4 7/10/10
22 4 7/10/10
11 12 8/1/10
;
run;

proc sort data=work.have;
	by oldid changedate;
run;

%global changes;

/* Declare recursive macro to construct the sequence of ID changes */
%macro getChanges(id);
	%local newid date;
	%let newid=;
	%let date=;
	data _null_;
		set work.have(where=(oldid=&amp;amp;id));
		call symputx('newid', newid);
		call symputx('date',changedate);
	run;
	%if %length(&amp;amp;newid)&amp;gt;0 %then
	%do;
		%let changes=&amp;amp;changes/&amp;amp;newid:&amp;amp;date;
		%getChanges(&amp;amp;newid);
	%end;
%mend;

/* Create a template output data set of Top/Starting/Root Original Ids */
proc sql;
	create table work.want AS
	select 
		. AS asof length=8 /* Place holder */
		,a.oldid AS origid length=4
		,. AS currid length=4 
		,. AS changecount length=3
	from work.have a
	where not exists (select 'x' from work.have b where a.oldid =b.newid);
quit;

data work.want(DROP=rc changes);
	SET work.want;
	call symput('changes','');
	rc = dosubl('%getChanges('||origid||')');
	changes = symget('changes');
	changecount= countc(changes,'/');
	currid = scan(scan(changes,-1,'/'),1,':');
	asof =  INPUT(scan(scan(changes,-1,'/'),2,':'),best.);
	format asof mmddyy10.;
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Hope this helps,&lt;/P&gt;
&lt;P&gt;Ahmed&lt;/P&gt;</description>
      <pubDate>Wed, 05 Apr 2023 19:52:08 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868341#M343016</guid>
      <dc:creator>AhmedAl_Attar</dc:creator>
      <dc:date>2023-04-05T19:52:08Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868447#M343063</link>
      <description>&lt;P&gt;Thanks, Ahmed.&lt;/P&gt;&lt;P&gt;The output has duplicate rows as shown below and it does not include the origid (1) or the correct changecount (number of times id 4&amp;nbsp; changed from the original ID), which should be 3 (1-&amp;gt;2, 2-&amp;gt;3, 3-&amp;gt;4).&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;TABLE border="1"&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;asof&lt;/TD&gt;&lt;TD&gt;origid&lt;/TD&gt;&lt;TD&gt;currid&lt;/TD&gt;&lt;TD&gt;changecount&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;07/10/2010&lt;/TD&gt;&lt;TD&gt;.&lt;/TD&gt;&lt;TD&gt;4&lt;/TD&gt;&lt;TD&gt;2&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;07/10/2010&lt;/TD&gt;&lt;TD&gt;.&lt;/TD&gt;&lt;TD&gt;4&lt;/TD&gt;&lt;TD&gt;2&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;07/10/2010&lt;/TD&gt;&lt;TD&gt;.&lt;/TD&gt;&lt;TD&gt;4&lt;/TD&gt;&lt;TD&gt;2&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;</description>
      <pubDate>Thu, 06 Apr 2023 12:23:18 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868447#M343063</guid>
      <dc:creator>bobsas1</dc:creator>
      <dc:date>2023-04-06T12:23:18Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868455#M343070</link>
      <description>Hi &lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/427679"&gt;@bobsas1&lt;/a&gt;&lt;BR /&gt;Can you please tell us what you expecting to see/get based on the sample data you have included in your original attachment?&lt;BR /&gt;&lt;BR /&gt;It will help clarify lots of potential misunderstanding and misinterpretation.&lt;BR /&gt;&lt;BR /&gt;Thanks,&lt;BR /&gt;Ahmed</description>
      <pubDate>Thu, 06 Apr 2023 13:40:38 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868455#M343070</guid>
      <dc:creator>AhmedAl_Attar</dc:creator>
      <dc:date>2023-04-06T13:40:38Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868466#M343079</link>
      <description>&lt;P&gt;&lt;SPAN&gt;Hi Ahmed,&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&lt;SPAN&gt;My apologies.&amp;nbsp; I think I included that in the original post, but maybe it didn't display well:&lt;/SPAN&gt;&lt;/P&gt;&lt;TABLE border="1"&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;&lt;P&gt;&lt;SPAN&gt;asof&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;TD&gt;&lt;P&gt;&lt;SPAN&gt;origid&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;TD&gt;&lt;P&gt;&lt;SPAN&gt;currid&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;TD&gt;&lt;P&gt;&lt;SPAN&gt;changecount&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;&lt;SPAN&gt;08/15/2010&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;1 &lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;4&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;&lt;SPAN&gt;3 &lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;P&gt;-AND-&lt;/P&gt;&lt;TABLE border="1"&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;&lt;P&gt;&lt;SPAN&gt;changedate&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;TD&gt;&lt;P&gt;&lt;SPAN&gt;oldid&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;TD&gt;&lt;P&gt;&lt;SPAN&gt;newid&lt;/SPAN&gt;&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;&lt;SPAN&gt;01/01/2010&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;1&lt;/TD&gt;&lt;TD&gt;2&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;&lt;SPAN&gt;07/01/2010&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;2&lt;/TD&gt;&lt;TD&gt;3&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;&lt;SPAN&gt;07/10/2010&lt;/SPAN&gt;&lt;/TD&gt;&lt;TD&gt;3&lt;/TD&gt;&lt;TD&gt;4&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;</description>
      <pubDate>Thu, 06 Apr 2023 15:26:41 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868466#M343079</guid>
      <dc:creator>bobsas1</dc:creator>
      <dc:date>2023-04-06T15:26:41Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868505#M343090</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/427679"&gt;@bobsas1&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Try this&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
	attrib oldid newid length=8 changedate informat=mmddyy10. format=mmddyy10.;
	input oldid newid changedate;
	datalines;
1 2 1/1/10
10 11 1/1/10
2 3 7/1/10
3 4 7/10/10
22 4 7/10/10
11 12 8/1/10
;
run;

proc sort data=work.have;
	by oldid changedate;
run;

%global changes;

/* Declare recursive macro to construct the sequence of ID changes */
%macro getChanges(id,outDs);
	%local newid date;
	%let newid=;
	%let date=;
	data child;
		set work.have(where=(oldid=&amp;amp;id));
		call symputx('newid', newid);
		call symputx('date',changedate);
	run;
	%if %length(&amp;amp;newid)&amp;gt;0 %then
	%do;
		PROC APPEND BASE=&amp;amp;outDs DATA=child; RUN;
		%let changes=&amp;amp;changes/&amp;amp;newid:&amp;amp;date;
		%getChanges(&amp;amp;newid,&amp;amp;outDs);
	%end;
%mend;

/* Create a template output data set of Top/Starting/Root Original Ids */
proc sql;
	create table work.want AS
	select 
		'15aug2010'd AS asof length=8 format=mmddyy10.
		,a.oldid AS origid length=4
		,. AS currid length=4 
		,. AS changecount length=3
	from work.have a
	where not exists (select 'x' from work.have b where a.oldid =b.newid);
quit;

data work.want(DROP=rc changes);
	SET work.want;
	/* Reset */
	call symput('changes','');
	dsName=cats('_',origid,'_children');
	rc = dosubl('proc delete data='||dsName||'; run;');

	/* Get Children(s) */
	rc = dosubl('%getChanges('||origid||','||dsName||')');
	changes = symget('changes');
	changecount= countc(changes,'/');
	currid = scan(scan(changes,-1,'/'),1,':');
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;This version of the code will generate separate data set for every set of children records, and the name of the data set will be stored in a column called: 'dsName'&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;TABLE&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="125"&gt;
&lt;P&gt;asof&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;origid&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;currid&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;changecount&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;dsName&lt;/P&gt;
&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="125"&gt;
&lt;P&gt;08/15/2010&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;_1_children&lt;/P&gt;
&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="125"&gt;
&lt;P&gt;08/15/2010&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 10&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 12&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;_10_children&lt;/P&gt;
&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="125"&gt;
&lt;P&gt;08/15/2010&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 22&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 4&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&lt;/P&gt;
&lt;/TD&gt;
&lt;TD width="125"&gt;
&lt;P&gt;_22_children&lt;/P&gt;
&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;</description>
      <pubDate>Thu, 06 Apr 2023 20:03:30 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868505#M343090</guid>
      <dc:creator>AhmedAl_Attar</dc:creator>
      <dc:date>2023-04-06T20:03:30Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868526#M343106</link>
      <description>&lt;P&gt;Hi Ahmed,&lt;/P&gt;&lt;P&gt;The code you provided is excellent!&amp;nbsp; How do I modify it so that the recursive macro only evaluates the table "have" for an ID that I specify, such as if I only want the historical path for ID 4? In practice, I will have a set of current ID's I want the history of, so it will be useful if the code references a separate table (instead of just specifying ID "4" in the code) that contains a list of current ID's I want the history.&lt;/P&gt;&lt;P&gt;Sincerely,&lt;/P&gt;&lt;P&gt;R&lt;/P&gt;</description>
      <pubDate>Thu, 06 Apr 2023 21:08:09 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868526#M343106</guid>
      <dc:creator>bobsas1</dc:creator>
      <dc:date>2023-04-06T21:08:09Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868588#M343128</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/427679"&gt;@bobsas1&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;How about this approach&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/* Create sample data of all available IDs and their changes over time */
data all_ids;
	attrib oldid newid length=8 changedate informat=mmddyy10. format=mmddyy10.;
	input oldid newid changedate;
	datalines;
1 2 1/1/10
2 3 7/1/10
3 4 7/10/10
10 11 1/1/10
11 12 8/1/10
;
run;

/* Declare recursive macro to construct the sequence of ID changes */
%macro getChanges(id,outDs,allIdsDs);
	%local oldid date;
	%let oldid=;
	%let date=;
	data child;
		set &amp;amp;allIdsDs(where=(newid=&amp;amp;id));
		call symputx('oldid', oldid);
		call symputx('date',changedate);
	run;
	%if %length(&amp;amp;oldid)&amp;gt;0 %then
	%do;
		PROC APPEND BASE=&amp;amp;outDs DATA=child; RUN;
		%let changes=&amp;amp;changes/&amp;amp;oldid:&amp;amp;date;
		%getChanges(&amp;amp;oldid,&amp;amp;outDs,&amp;amp;allIdsDs);
	%end;
%mend;


%global changes;

%macro getIdChangeHistory(
  p_id=							/* ID value to extract change history for */
, p_asOfDate= %sysfunc(day())	/* SAS date. Default: Current date */
, p_idsDsName=					/* Data set name of all existing IDs */
, p_outSmryDsName=				/* Output Data set of changes summary */
, p_outChngHistDsName=			/* Output Data set of changes records */
);

	/* Create two data sets with single record in each */
	DATA 
		&amp;amp;p_outSmryDsName(KEEP=asof origid currid changecount)
		&amp;amp;p_outChngHistDsName(KEEP=oldid newid changedate);

		LENGTH asof 8 origid currid 4 changecount 3; 
		FORMAT asof mmddyy10.;

		/* Read change record */
		SET &amp;amp;p_idsDsName(where=(newid = &amp;amp;p_id));

 		/* Store change record */
		OUTPUT &amp;amp;p_outChngHistDsName;

		/* Initialize change summary fields */
		origid = oldid; 
		currid = newid;
		asof = &amp;amp;p_asOfDate; 
		changecount = .;
		/* Store partial/incomplete change summary info */
		OUTPUT &amp;amp;p_outSmryDsName; 
	RUN;

	/* Finalize all needed output data sets */
	DATA &amp;amp;p_outSmryDsName(DROP=rc changes);

		SET &amp;amp;p_outSmryDsName;
		call symput('changes',cats(origid,':',asof));

		rc = dosubl('%getChanges('||origid||",&amp;amp;p_outChngHistDsName,&amp;amp;p_idsDsName)");
		changes = symget('changes');
		changecount= countc(changes,'/')+1;
		origid = scan(scan(changes,-1,'/'),1,':');
	run;
	PROC SORT DATA=&amp;amp;p_outChngHistDsName;
		BY oldid changedate;
	RUN;
%mend getIdChangeHistory;

/* Usage examples */
%getIdChangeHistory(p_id=4, p_asOfDate='15Aug2010'd, p_idsDsName=work.all_ids, p_outSmryDsName=work._4_smry, p_outChngHistDsName=work._4_changeHistory);
%getIdChangeHistory(p_id=12, p_asOfDate=%sysfunc(date()), p_idsDsName=work.all_ids, p_outSmryDsName=work._12_smry, p_outChngHistDsName=work._12_changeHistory);&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Note: You can name your output data sets as you like. The names I used were for illustrations only.&lt;/P&gt;</description>
      <pubDate>Fri, 07 Apr 2023 12:23:45 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868588#M343128</guid>
      <dc:creator>AhmedAl_Attar</dc:creator>
      <dc:date>2023-04-07T12:23:45Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868614#M343140</link>
      <description>&lt;PRE&gt;&lt;CODE class=""&gt;/*this code runs with no errors, but does not produce any output tables except "have"*/&lt;BR /&gt;&lt;BR /&gt;%global changes;

%macro getidchangehistory(
p_id=4
,p_asfdate='15Aug2020'd
,p_idsdsname=work.have
,p_outsmrydsname=work.changes
,p_outchnghistsaname=work.chngrec
);&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Fri, 07 Apr 2023 15:00:25 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868614#M343140</guid>
      <dc:creator>bobsas1</dc:creator>
      <dc:date>2023-04-07T15:00:25Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868619#M343143</link>
      <description>Have you checked you work library?&lt;BR /&gt;The code does not use proc print.</description>
      <pubDate>Fri, 07 Apr 2023 15:10:06 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868619#M343143</guid>
      <dc:creator>AhmedAl_Attar</dc:creator>
      <dc:date>2023-04-07T15:10:06Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868871#M343244</link>
      <description>&lt;P&gt;Hi Ahmed,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Yes. Only table "Have" exists in the library&amp;nbsp; "Work".&lt;/P&gt;&lt;P&gt;The p_asofdate I actually used is '15Aug2010'd&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Regards,&lt;/P&gt;</description>
      <pubDate>Mon, 10 Apr 2023 15:14:45 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868871#M343244</guid>
      <dc:creator>bobsas1</dc:creator>
      <dc:date>2023-04-10T15:14:45Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868875#M343247</link>
      <description>Hi,&lt;BR /&gt;That's interesting!!&lt;BR /&gt;I just copied the entire code I had sent you, changed the first data set name from all_ids to have, and updated the usage examples to:&lt;BR /&gt;/* Usage examples */&lt;BR /&gt;%getIdChangeHistory(p_id=4, p_asOfDate='15Aug2010'd, p_idsDsName=work.have, p_outSmryDsName=work._4_smry, p_outChngHistDsName=work._4_changeHistory);&lt;BR /&gt;%getIdChangeHistory(p_id=12, p_asOfDate=%sysfunc(date()), p_idsDsName=work.have, p_outSmryDsName=work._12_smry, p_outChngHistDsName=work._12_changeHistory);&lt;BR /&gt;&lt;BR /&gt;And everything works as expected!?</description>
      <pubDate>Mon, 10 Apr 2023 15:28:34 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868875#M343247</guid>
      <dc:creator>AhmedAl_Attar</dc:creator>
      <dc:date>2023-04-10T15:28:34Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868982#M343284</link>
      <description>&lt;P&gt;Hi Ahmed,&lt;/P&gt;&lt;P&gt;Thank you so much.&amp;nbsp; My apologies, but I misunderstood originally.&amp;nbsp; It works now (however, table work.child is null).&amp;nbsp; I hope you can help with this other part- please advise if a new thread is warranted:&lt;/P&gt;&lt;P&gt;I wanted a section of the code that allows me to input many ID's from a separate table and have the macro produce one table (like p_outsmrydsname) with the results combined for all id's.&amp;nbsp; For example:&lt;/P&gt;&lt;P&gt;1. The new table with many ID's that I want the macro to produce origid, currid, changecount results would like like this:&lt;/P&gt;&lt;TABLE border="1"&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;currid&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;4&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;12&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;&lt;P&gt;...and so on...&lt;/P&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;2. and the output would look something like:&lt;/P&gt;&lt;TABLE border="1"&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;asof&lt;/TD&gt;&lt;TD&gt;origid&lt;/TD&gt;&lt;TD&gt;currid&lt;/TD&gt;&lt;TD&gt;changecount&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;08/15/2010&lt;/TD&gt;&lt;TD&gt;1&lt;/TD&gt;&lt;TD&gt;4&lt;/TD&gt;&lt;TD&gt;3&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;08/15/2010&lt;/TD&gt;&lt;TD&gt;22&lt;/TD&gt;&lt;TD&gt;4&lt;/TD&gt;&lt;TD&gt;1&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;08/15/2010&lt;/TD&gt;&lt;TD&gt;10&lt;/TD&gt;&lt;TD&gt;12&lt;/TD&gt;&lt;TD&gt;2&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;and so on....&lt;/TD&gt;&lt;TD&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD&gt;&amp;nbsp;&lt;/TD&gt;&lt;TD&gt;&amp;nbsp;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;</description>
      <pubDate>Tue, 11 Apr 2023 04:17:14 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/868982#M343284</guid>
      <dc:creator>bobsas1</dc:creator>
      <dc:date>2023-04-11T04:17:14Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/869018#M343298</link>
      <description>&lt;P&gt;Can you post data in usable form an show the output you expect, please.&lt;/P&gt;</description>
      <pubDate>Tue, 11 Apr 2023 08:28:23 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/869018#M343298</guid>
      <dc:creator>andreas_lds</dc:creator>
      <dc:date>2023-04-11T08:28:23Z</dc:date>
    </item>
    <item>
      <title>Re: Hash Objects | Count changes to a parent ID over time and list history of related child ID's</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/869078#M343305</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/427679"&gt;@bobsas1&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Here it is&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;
/* Declare recursive macro to construct the sequence of ID changes */
%macro getChanges(id,outDs,allIdsDs);
	%local oldid date;
	%let oldid=;
	%let date=;
	data child;
		set &amp;amp;allIdsDs(where=(newid=&amp;amp;id));
		call symputx('oldid', oldid);
		call symputx('date',changedate);
	run;
	%if %length(&amp;amp;oldid)&amp;gt;0 %then
	%do;
		PROC APPEND BASE=&amp;amp;outDs DATA=child; RUN;
		%let changes=&amp;amp;changes/&amp;amp;oldid:&amp;amp;date;
		%getChanges(&amp;amp;oldid,&amp;amp;outDs,&amp;amp;allIdsDs);
	%end;
%mend getChanges;


%global changes;

%macro getIdChangeHistory(
  p_id=							/* ID value to extract change history for */
, p_asOfDate= %sysfunc(day())	/* SAS date. Default: Current date */
, p_idsDsName=					/* Data set name of all existing IDs */
, p_outSmryDsName=				/* Output Data set of changes summary */
, p_outChngHistDsName=			/* Output Data set of changes records */
);

	/* Create two data sets with single record in each */
	DATA 
		&amp;amp;p_outSmryDsName(KEEP=asof origid currid changecount)
		&amp;amp;p_outChngHistDsName(KEEP=oldid newid changedate);

		LENGTH asof 8 origid currid 4 changecount 3; 
		FORMAT asof mmddyy10.;

		/* Read change record */
		SET &amp;amp;p_idsDsName(where=(newid = &amp;amp;p_id));

 		/* Store change record */
		OUTPUT &amp;amp;p_outChngHistDsName;

		/* Initialize change summary fields */
		origid = oldid; 
		currid = newid;
		asof = &amp;amp;p_asOfDate; 
		changecount = .;
		/* Store partial/incomplete change summary info */
		OUTPUT &amp;amp;p_outSmryDsName; 
	RUN;

	/* Finalize all needed output data sets */
	DATA &amp;amp;p_outSmryDsName(DROP=rc changes);

		SET &amp;amp;p_outSmryDsName;
		call symput('changes',cats(origid,':',asof));

		rc = dosubl('%getChanges('||origid||",&amp;amp;p_outChngHistDsName,&amp;amp;p_idsDsName)");
		changes = symget('changes');
		changecount= countc(changes,'/')+1;
		origid = scan(scan(changes,-1,'/'),1,':');
	run;
	PROC SORT DATA=&amp;amp;p_outChngHistDsName;
		BY oldid changedate;
	RUN;
%mend getIdChangeHistory;

/* Create sample data of all available IDs and their changes over time */
data work.all_ids;
	attrib oldid newid length=8 changedate informat=mmddyy10. format=mmddyy10.;
	input oldid newid changedate;
	datalines;
1 2 1/1/10
10 11 1/1/10
2 3 7/1/10
3 4 7/10/10
22 4 7/10/10
11 12 8/1/10
;
run;

/* New: Added to construct a table of unique IDs with change history */
proc sql;
	create table work.unique_currIds AS
	select distinct a.newid as currID
	FROM work.all_ids a
	where not exists (select 'x' from work.all_ids b where b.oldid=a.newid);
quit;

/* New: Declare new macro to get the Change history Summary for a given list of IDs */
%macro getChangeSummary(p_inCurrIdDsName=, p_varName=, p_date=, p_inAllIdsDsName=, p_outChangeSummaryDsName=); 

	/* Prep a file for dynamically generated code */
	FILENAME dyncode TEMP;
	
	/* Read the input data set and construct macro call for every record */
	DATA _NULL_;
		FILE dyncode lrecl=300;
		LENGTH stmt $300 id_smry_ds id_hstry_ds $40;
		SET &amp;amp;p_inCurrIdDsName;
		
		/* construct the parts of the final macro call */
		id_smry_ds  = CATX('_','work.',&amp;amp;p_varName,'smry');
		id_hstry_ds = CATX('_','work.',&amp;amp;p_varName,'changeHistory');
		
		/* put together the macro call and write it out */
		stmt =CATS('%getIdChangeHistory(p_id=',&amp;amp;p_varName,",p_asOfDate=&amp;amp;p_date , p_idsDsName=&amp;amp;p_inAllIdsDsName ,");
		stmt =CATS(stmt,'p_outSmryDsName=',id_smry_ds,', p_outChngHistDsName=',id_hstry_ds,');');
		PUT stmt;
		
		PUTLOG 'NOTE: writing out the following macro call:' stmt ; 
		
		/* Write out Proc Append statement to construct single Changes Summary data set */
		id_smry_ds = STRIP(id_smry_ds);
		put "PROC APPEND BASE=&amp;amp;p_outChangeSummaryDsName DATA=" id_smry_ds "; RUN;";
	RUN;
	
	/* Execute the dynamic code */
	%include dyncode;
	;;;;
%mend getChangeSummary;

%getChangeSummary(p_inCurrIdDsName=work.unique_currIds
, p_varName=currID
, p_date='15Aug2010'd
, p_inAllIdsDsName=work.all_ids
, p_outChangeSummaryDsName=work.IdsChangeSummary)&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;All was needed is this new macro&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;/* New: Declare new macro to get the Change history Summary for a given list of IDs */
%macro getChangeSummary(p_inCurrIdDsName=, p_varName=, p_date=, p_inAllIdsDsName=, p_outChangeSummaryDsName=); 

	/* Prep a file for dynamically generated code */
	FILENAME dyncode TEMP;
	
	/* Read the input data set and construct macro call for every record */
	DATA _NULL_;
		FILE dyncode lrecl=300;
		LENGTH stmt $300 id_smry_ds id_hstry_ds $40;
		SET &amp;amp;p_inCurrIdDsName;
		
		/* construct the parts of the final macro call */
		id_smry_ds  = CATX('_','work.',&amp;amp;p_varName,'smry');
		id_hstry_ds = CATX('_','work.',&amp;amp;p_varName,'changeHistory');
		
		/* put together the macro call and write it out */
		stmt =CATS('%getIdChangeHistory(p_id=',&amp;amp;p_varName,",p_asOfDate=&amp;amp;p_date , p_idsDsName=&amp;amp;p_inAllIdsDsName ,");
		stmt =CATS(stmt,'p_outSmryDsName=',id_smry_ds,', p_outChngHistDsName=',id_hstry_ds,');');
		PUT stmt;
		
		PUTLOG 'NOTE: writing out the following macro call:' stmt ; 
		
		/* Write out Proc Append statement to construct single Changes Summary data set */
		id_smry_ds = STRIP(id_smry_ds);
		put "PROC APPEND BASE=&amp;amp;p_outChangeSummaryDsName DATA=" id_smry_ds "; RUN;";
	RUN;
	
	/* Execute the dynamic code */
	%include dyncode;
	;;;;
%mend getChangeSummary;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Which is really nothing more than a wrapper for constructing the&lt;SPAN&gt;&amp;nbsp;%getIdChangeHistory (....) macro call.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Check out the SAS log to see what I'm talking about.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Hope this helps&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 11 Apr 2023 11:07:26 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Hash-Objects-Count-changes-to-a-parent-ID-over-time-and-list/m-p/869078#M343305</guid>
      <dc:creator>AhmedAl_Attar</dc:creator>
      <dc:date>2023-04-11T11:07:26Z</dc:date>
    </item>
  </channel>
</rss>

