<?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: Merging Inexact Dates on Range with Multiple Observations in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/809516#M319240</link>
    <description>&lt;P&gt;If you could build a linktable that looks like this:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;TABLE class="lia-align-center" style="height: 210px; width: 30%;" border="1" width="30%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;Link&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;OP_dummy&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;FU_dummy&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;MED_dummy&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;2&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;3&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;4&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;5&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;6&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You could loop over the rows (L=1 to 6) with logic like this, where _nlink=6:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;  do L=1 to _nlink;
    call missing (of _sentinel1--_sentinel2);
    if _linkdates{L,1}^=. then set optest;
    if _linkdates{L,2}^=. then set futest;
    if _linkdates{L,3}^=. then set medtest;
    output;
  end;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The above assumes the _sentinel1 variable is to the left of the variables from the 3 datasets, and _sentinel2 to the right, and the two-way array &lt;EM&gt;&lt;STRONG&gt;_linkdates&lt;/STRONG&gt;&lt;/EM&gt; includes only the rightmost 3 columns above.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;So the task obviously is to build that link table in a first pass of each ID, so that the second pass could use the code above:&amp;nbsp; The below does that:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data optest; input id op date_op MMDDYY10.; format date_op MMDDYY10.; datalines;
1 1 02/12/2020
1 1 02/13/2020
1 1 03/03/2021
1 1 03/05/2021
1 1 03/11/2021
;run;
 
data futest; input id fu date_fu MMDDYY10.; format date_fu MMDDYY10.; datalines;
1 1 03/05/2020
1 1 03/16/2021
1 1 01/16/2022
;run;
 
data medtest; input id med date_med MMDDYY10.; format date_med MMDDYY10.; datalines;
1 1 03/25/2021

data want (drop=_: L) ;
  retain _sentinel1 . ;
  if 0 then set optest futest medtest;
  retain _sentinel2 . ;

  array _linkdates {40,3};     *Accomodate up to 40 links of 3 dates (date_op,date_fu,date_med)**;

  _nlink=0;
  do until (last.id);
    set optest  (keep=id date_op  rename=(date_op=_srtdate)  in=inop)
        futest  (keep=id date_fu  rename=(date_fu=_srtdate)  in=infu)
        medtest (keep=id date_med rename=(date_med=_srtdate) in=inmd) ;
    by id _srtdate;

    if inop then do;
      _nlink+1;     **New link**;
      _linkdates{_nlink,1}=_srtdate;   ** Renamed from DATE_OP **;
    end;
    else if infu then do;
      if _nlink=0 then L=1;           **In case FUTEST is 1st record for this id**;
      else do L=1 to _nlink until (_srtdate-30 &amp;lt;= _linkdates{L,1});
      end;
      if L&amp;gt;_nlink then _nlink=L;   **New link**;
      _linkdates{L,2}=_srtdate;    *DATE_FU in second column;
    end;

    else if inmd then do;
      if _nlink=0 then L=1;           **In case MEDTEST is 1st record for this id**;
      else do L=1 to _nlink until (_srtdate-30 &amp;lt;= _linkdates{L,1} and _srtdate&amp;gt;=_linkdates{L,2});
      end;
      if L&amp;gt;_nlink then _nlink=L;   **New link**;
      _linkdates{L,3}=_srtdate;   *DATE_MED in third column;
    end; 
  end;

  do L=1 to _nlink;
    call missing (of _sentinel1--_sentinel2);
    if _linkdates{L,1}^=. then set optest;
    if _linkdates{L,2}^=. then set futest;
    if _linkdates{L,3}^=. then set medtest;
    output;
  end;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Be sure to set the row size of the _linkdates array to accomodated the largest number of linkages expected for any single ID.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Note the &lt;EM&gt;&lt;STRONG&gt;else do&lt;/STRONG&gt;&lt;/EM&gt; loops have no internal code.&amp;nbsp; They just have a stopping condition based on the date relationships you posted.&amp;nbsp; If none of the pre-existing links satisfy the stopping condition, then the index variable L will be exactly 1 greater than the prior _nlinks value - indicating need for a new link id.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Actually the _linkdates table in the program doesn't used dummy variables in the tables cells.&amp;nbsp; It uses date values.&lt;/P&gt;</description>
    <pubDate>Sun, 24 Apr 2022 21:37:54 GMT</pubDate>
    <dc:creator>mkeintz</dc:creator>
    <dc:date>2022-04-24T21:37:54Z</dc:date>
    <item>
      <title>Merging Inexact Dates on Range with Multiple Observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808942#M318978</link>
      <description>&lt;P&gt;I'm having trouble merging datasets on date ranges.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;A couple problems encountered are 1) only selecting the first observation per dataset that meets the criteria, and 2) not duplicating that observation on other rows.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In this sample data, any follow-up (fu) and medication (med) observations which occur within 30 days of the OP date, would be merged once and then not used again. There are several datasets like this, so sequential merge/join statements would work fine.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data optest; input id op date_op MMDDYY10.; format date_op MMDDYY10.; datalines;
1 1 02/12/2020
1 1 02/13/2020
1 1 03/03/2021
1 1 03/05/2021
1 1 03/11/2021
;run;
proc print data=optest; run;
 
data futest; input id fu date_fu MMDDYY10.; format date_fu MMDDYY10.; datalines;
1 1 03/05/2020
1 1 03/16/2021
1 1 01/16/2022
;run;
proc print data=futest; run;
 
data medtest; input id med date_med MMDDYY10.; format date_med MMDDYY10.; datalines;
1 1 03/25/2021
;run;
proc print data=medtest; run;
 &lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Want:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="xmsonormal" style="text-autospace: none;"&gt;&lt;SPAN&gt;&amp;nbsp;id&amp;nbsp;&amp;nbsp;&amp;nbsp; op&amp;nbsp;&amp;nbsp;&amp;nbsp; date_op&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; fu&amp;nbsp;&amp;nbsp; &amp;nbsp; date_fu&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; med&amp;nbsp; &amp;nbsp; &amp;nbsp;date_med&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="xmsonormal" style="text-autospace: none;"&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="xmsonormal" style="text-autospace: none;"&gt;&lt;SPAN&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp; 02/12/2020&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 03/05/2020&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="xmsonormal" style="text-autospace: none;"&gt;&lt;SPAN&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp; 02/13/2020&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="xmsonormal" style="text-autospace: none;"&gt;&lt;SPAN&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp; 03/03/2021&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 03/16/2021&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;03/25/2021&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="xmsonormal" style="text-autospace: none;"&gt;&lt;SPAN&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp; 03/05/2021&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="xmsonormal" style="text-autospace: none;"&gt;&lt;SPAN&gt;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 1&amp;nbsp;&amp;nbsp;&amp;nbsp; 03/11/2021&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="xmsonormal" style="text-autospace: none;"&gt;&lt;SPAN&gt;&amp;nbsp; 1&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;1&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 01/16/2022&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class="xmsonormal" style="text-autospace: none;"&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 20 Apr 2022 22:38:35 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808942#M318978</guid>
      <dc:creator>moreka</dc:creator>
      <dc:date>2022-04-20T22:38:35Z</dc:date>
    </item>
    <item>
      <title>Merging Data on Closest Date Values (without replacement)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808921#M318989</link>
      <description>&lt;P&gt;The situation is that i have 3 datasets that are all logging different things about a subject. The initial visit, follow up visit and medication prescribe date. I need to make a "best guess" as to when the follow up visit corresponds to the initial and when meds corresponds to the follow up (or initial if follow up is unavailable.) It cant be the absolute value of the closest date because a follow up can not happen BEFORE the initial and meds cant be prescribed before a visit. Also, once a follow up visit have been used to proceed an initial it can not be used again, so I need a way to exclude if from being considered further.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I have tried a few different approaches with merges, sets and SQLs but have not found anything that will get me to where i want to be. Does anyone have experience with this kind of merge or filtering.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I am open to all possibilities so if there is a better path feel free.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;Want:&lt;BR /&gt;id&amp;nbsp; &amp;nbsp;op&amp;nbsp; &amp;nbsp; &amp;nbsp;date_op&amp;nbsp; &amp;nbsp; &amp;nbsp; fu&amp;nbsp; &amp;nbsp;date_fu&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;med&amp;nbsp; &amp;nbsp;date_med&lt;BR /&gt;&lt;BR /&gt;1&amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; 02/12/2020&amp;nbsp; &amp;nbsp; &amp;nbsp;1 03/05/2020&lt;BR /&gt;1&amp;nbsp; &amp;nbsp; &amp;nbsp;1 02/13/2020 &lt;BR /&gt;1&amp;nbsp; &amp;nbsp; &amp;nbsp;1 03/03/2021&amp;nbsp; &amp;nbsp; &amp;nbsp; 1 03/16/2021&amp;nbsp; &amp;nbsp; &amp;nbsp; 1 03/25/2021&lt;BR /&gt;1&amp;nbsp; &amp;nbsp; &amp;nbsp;1 03/05/2021&lt;BR /&gt;1&amp;nbsp; &amp;nbsp; &amp;nbsp;1 03/11/2021&lt;BR /&gt;1&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; 1&amp;nbsp; 01/16/2022&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;data optest; 
input id op date_op MMDDYY10.; format date_op MMDDYY10.;
datalines;
1 1 02/12/2020
1 1 02/13/2020
1 1 03/03/2021
1 1 03/05/2021
1 1 03/11/2021
;run;
proc print data=optest; run;
 
 
data futest; 
input id fu date_fu MMDDYY10.; format date_fu MMDDYY10.;
datalines;
1 1 03/05/2020
1 1 03/16/2021
1 1 01/16/2022
;run;
proc print data=futest; run;
 
 
data medtest; 
input id med date_med MMDDYY10.; format date_med MMDDYY10.;
datalines;
1 1 03/25/2021
;run;
proc print data=medtest; run;
 
 
&lt;/PRE&gt;</description>
      <pubDate>Wed, 20 Apr 2022 20:56:43 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808921#M318989</guid>
      <dc:creator>GreyJoy</dc:creator>
      <dc:date>2022-04-20T20:56:43Z</dc:date>
    </item>
    <item>
      <title>Re: Merging Data on Closest Date Values (without replacement)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808936#M318990</link>
      <description>&lt;P&gt;I think this can best done by a data step.&amp;nbsp; But you need to establish a few rules of assignment of an futest and/or medtest record to a specific optest record.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For instance:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Why is the 03/05/2020 futest record assigned to the 02/12/2020 optest record, instead of the closer 02/13/2020 optest record?&amp;nbsp; &amp;nbsp;How far apart must the optest records be to use the one closer to the futest record?&lt;/LI&gt;
&lt;LI&gt;How long an interval must there be for a potential assignment to become "stale"?&amp;nbsp; &amp;nbsp;You have your last futest (1/16/2022) record assigned to no optest record, presumably because the latest preceding optest record is ten months prior (3/11/2021).&lt;/LI&gt;
&lt;LI&gt;Can a date_med, while following a date_op, precede the associated date_fu?&lt;/LI&gt;
&lt;LI&gt;Can a date_fu&amp;nbsp; (or date_med) &lt;EM&gt;&lt;STRONG&gt;be equal&lt;/STRONG&gt;&lt;/EM&gt; to a date_op, or must it strictly follow date_op?&amp;nbsp; &amp;nbsp;If it must strictly follow, is a single day later sufficient?&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 20 Apr 2022 22:17:55 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808936#M318990</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2022-04-20T22:17:55Z</dc:date>
    </item>
    <item>
      <title>Re: Merging Inexact Dates on Range with Multiple Observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808946#M318982</link>
      <description>&lt;P&gt;Looks like this is the same as this post&lt;BR /&gt;&lt;A href="https://communities.sas.com/t5/SAS-Programming/Merging-Data-on-Closest-Date-Values-without-replacement/m-p/808921" target="_blank"&gt;https://communities.sas.com/t5/SAS-Programming/Merging-Data-on-Closest-Date-Values-without-replacement/m-p/808921&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Wed, 20 Apr 2022 23:38:05 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808946#M318982</guid>
      <dc:creator>Sajid01</dc:creator>
      <dc:date>2022-04-20T23:38:05Z</dc:date>
    </item>
    <item>
      <title>Re: Merging Inexact Dates on Range with Multiple Observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808950#M318983</link>
      <description>&lt;P&gt;Two different OP's asking the same question with the same data?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Is this a homework assignment?&lt;/P&gt;</description>
      <pubDate>Thu, 21 Apr 2022 00:02:05 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808950#M318983</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2022-04-21T00:02:05Z</dc:date>
    </item>
    <item>
      <title>Re: Merging Data on Closest Date Values (without replacement)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808951#M318991</link>
      <description>&lt;P&gt;This is the same question as&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;A href="https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808942/highlight/false#M318978" target="_blank"&gt;Merging Inexact Dates on Range with Multiple Obser... - SAS Support Communities&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Why are two OP's asking the same question?&lt;/P&gt;</description>
      <pubDate>Thu, 21 Apr 2022 00:03:08 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808951#M318991</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2022-04-21T00:03:08Z</dc:date>
    </item>
    <item>
      <title>Re: Merging Inexact Dates on Range with Multiple Observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808952#M318985</link>
      <description>Nah, it's a problem I've been dealing with for a while and reached out with an example. He also worked on it for a while and encountered some of the same issues. I didn't know he'd posted about it earlier today.</description>
      <pubDate>Thu, 21 Apr 2022 00:08:38 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808952#M318985</guid>
      <dc:creator>moreka</dc:creator>
      <dc:date>2022-04-21T00:08:38Z</dc:date>
    </item>
    <item>
      <title>Re: Merging Inexact Dates on Range with Multiple Observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808956#M318992</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/46780"&gt;@moreka&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;OK.&amp;nbsp; I've merged the other thread into this one.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You have answered one of the questions I posted on the other thread - namely that linked DATE_FU and DATE_MED dates must be within 30 days of the DATE_OP.&amp;nbsp; So 30 days gap makes a potential link "stale".&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The other question is why is the 03/05/2020 FU_DATE linked to the 02/12/2020 DATE_OP, instead of the 02/13/2020 DATE_OP, which is closer?&amp;nbsp; &amp;nbsp;Is the rule to associate a DATE_FU and/or DATE_MED with the earliest preceding&amp;nbsp; non-stale DATE_OP ?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 21 Apr 2022 00:44:15 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808956#M318992</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2022-04-21T00:44:15Z</dc:date>
    </item>
    <item>
      <title>Re: Merging Data on Closest Date Values (without replacement)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808957#M318993</link>
      <description>Possibly because they are working on the same problem and both had the idea of asking SAS communities for help. &lt;BR /&gt;&lt;BR /&gt;Do you have any helpful input or just making random comments on posts?&lt;BR /&gt;</description>
      <pubDate>Thu, 21 Apr 2022 00:56:24 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808957#M318993</guid>
      <dc:creator>GreyJoy</dc:creator>
      <dc:date>2022-04-21T00:56:24Z</dc:date>
    </item>
    <item>
      <title>Re: Merging Data on Closest Date Values (without replacement)</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808962#M318994</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/351316"&gt;@GreyJoy&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;Possibly because they are working on the same problem and both had the idea of asking SAS communities for help. &lt;BR /&gt;&lt;BR /&gt;Do you have any helpful input or just making random comments on posts?&lt;BR /&gt;&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Then you both came to the right place.&amp;nbsp; But since you are working on the same problem, it will be better to work on this merged thread.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I'll repeat a couple of questions that I still have:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Must a DATE_FU actually &lt;EM&gt;&lt;STRONG&gt;follow&lt;/STRONG&gt;&lt;/EM&gt; a DATE_PO, or is a link between equal dates allowed?&lt;BR /&gt;&lt;BR /&gt;&lt;/LI&gt;
&lt;LI&gt;Can a DATE_MED precede a DATE_FU and be linked to the same DATE_PO?&lt;BR /&gt;&lt;BR /&gt;&lt;/LI&gt;
&lt;LI&gt;The first DATE_FU in your sample data could be linked to either the first or second DATE_PO.&amp;nbsp; It appears from your sample WANT outcome, that you have a rule to match a DATE_FU to the earliest preceding DATE_PO, even if there is a closer preceding DATE_PO.&amp;nbsp; Is that correct?&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 21 Apr 2022 03:03:06 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808962#M318994</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2022-04-21T03:03:06Z</dc:date>
    </item>
    <item>
      <title>Re: Merging Inexact Dates on Range with Multiple Observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808990#M319005</link>
      <description>&lt;P&gt;Thanks for merging these threads.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Theoretically, the FU and MED would be linked to the earliest non-stale (30 days) OP date, because potentially this is the participant's first of several OP encounters.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;However, in the absence of a reasonably straightforward solution, the closest OP to FU date is acceptable.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;To address your previous questions:&lt;/P&gt;
&lt;P&gt;1. A DATE_FU can &lt;STRONG&gt;equal&lt;/STRONG&gt; or &lt;STRONG&gt;follow&lt;/STRONG&gt; a DATE_OP.&lt;/P&gt;
&lt;P&gt;2. A DATE_MED &lt;STRONG&gt;cannot precede&lt;/STRONG&gt; a DATE_FU, but can be linked to the &lt;STRONG&gt;same&lt;/STRONG&gt; DATE_OP, if for instance, they are all on the same date.&lt;/P&gt;
&lt;P class="lia-indent-padding-left-60px"&gt;&amp;nbsp; Generally speaking:&amp;nbsp; &amp;nbsp; OP &amp;lt;= FU &amp;lt;= MED&lt;/P&gt;
&lt;P&gt;3. Answered above, but to reiterate, DATE_FU &amp;amp; DATE_MED are linked to the first non-stale OP instance, but the closest preceding OP is allowable.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/31461"&gt;@mkeintz&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;OL&gt;
&lt;LI&gt;Must a DATE_FU actually&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;EM&gt;&lt;STRONG&gt;follow&lt;/STRONG&gt;&lt;/EM&gt;&lt;SPAN&gt;&amp;nbsp;&lt;/SPAN&gt;a DATE_PO, or is a link between equal dates allowed?&lt;/LI&gt;
&lt;LI&gt;Can a DATE_MED precede a DATE_FU and be linked to the same DATE_PO?&lt;/LI&gt;
&lt;LI&gt;The first DATE_FU in your sample data could be linked to either the first or second DATE_PO.&amp;nbsp; It appears from your sample WANT outcome, that you have a rule to match a DATE_FU to the earliest preceding DATE_PO, even if there is a closer preceding DATE_PO.&amp;nbsp; Is that correct?&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 21 Apr 2022 10:10:06 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/808990#M319005</guid>
      <dc:creator>moreka</dc:creator>
      <dc:date>2022-04-21T10:10:06Z</dc:date>
    </item>
    <item>
      <title>Re: Merging Inexact Dates on Range with Multiple Observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/809516#M319240</link>
      <description>&lt;P&gt;If you could build a linktable that looks like this:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;TABLE class="lia-align-center" style="height: 210px; width: 30%;" border="1" width="30%"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;Link&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;OP_dummy&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;FU_dummy&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;MED_dummy&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;2&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;3&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;4&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;5&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD width="25%" height="30px"&gt;6&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;1&lt;/TD&gt;
&lt;TD width="25%" height="30px"&gt;&amp;nbsp;&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You could loop over the rows (L=1 to 6) with logic like this, where _nlink=6:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;  do L=1 to _nlink;
    call missing (of _sentinel1--_sentinel2);
    if _linkdates{L,1}^=. then set optest;
    if _linkdates{L,2}^=. then set futest;
    if _linkdates{L,3}^=. then set medtest;
    output;
  end;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The above assumes the _sentinel1 variable is to the left of the variables from the 3 datasets, and _sentinel2 to the right, and the two-way array &lt;EM&gt;&lt;STRONG&gt;_linkdates&lt;/STRONG&gt;&lt;/EM&gt; includes only the rightmost 3 columns above.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;So the task obviously is to build that link table in a first pass of each ID, so that the second pass could use the code above:&amp;nbsp; The below does that:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data optest; input id op date_op MMDDYY10.; format date_op MMDDYY10.; datalines;
1 1 02/12/2020
1 1 02/13/2020
1 1 03/03/2021
1 1 03/05/2021
1 1 03/11/2021
;run;
 
data futest; input id fu date_fu MMDDYY10.; format date_fu MMDDYY10.; datalines;
1 1 03/05/2020
1 1 03/16/2021
1 1 01/16/2022
;run;
 
data medtest; input id med date_med MMDDYY10.; format date_med MMDDYY10.; datalines;
1 1 03/25/2021

data want (drop=_: L) ;
  retain _sentinel1 . ;
  if 0 then set optest futest medtest;
  retain _sentinel2 . ;

  array _linkdates {40,3};     *Accomodate up to 40 links of 3 dates (date_op,date_fu,date_med)**;

  _nlink=0;
  do until (last.id);
    set optest  (keep=id date_op  rename=(date_op=_srtdate)  in=inop)
        futest  (keep=id date_fu  rename=(date_fu=_srtdate)  in=infu)
        medtest (keep=id date_med rename=(date_med=_srtdate) in=inmd) ;
    by id _srtdate;

    if inop then do;
      _nlink+1;     **New link**;
      _linkdates{_nlink,1}=_srtdate;   ** Renamed from DATE_OP **;
    end;
    else if infu then do;
      if _nlink=0 then L=1;           **In case FUTEST is 1st record for this id**;
      else do L=1 to _nlink until (_srtdate-30 &amp;lt;= _linkdates{L,1});
      end;
      if L&amp;gt;_nlink then _nlink=L;   **New link**;
      _linkdates{L,2}=_srtdate;    *DATE_FU in second column;
    end;

    else if inmd then do;
      if _nlink=0 then L=1;           **In case MEDTEST is 1st record for this id**;
      else do L=1 to _nlink until (_srtdate-30 &amp;lt;= _linkdates{L,1} and _srtdate&amp;gt;=_linkdates{L,2});
      end;
      if L&amp;gt;_nlink then _nlink=L;   **New link**;
      _linkdates{L,3}=_srtdate;   *DATE_MED in third column;
    end; 
  end;

  do L=1 to _nlink;
    call missing (of _sentinel1--_sentinel2);
    if _linkdates{L,1}^=. then set optest;
    if _linkdates{L,2}^=. then set futest;
    if _linkdates{L,3}^=. then set medtest;
    output;
  end;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Be sure to set the row size of the _linkdates array to accomodated the largest number of linkages expected for any single ID.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Note the &lt;EM&gt;&lt;STRONG&gt;else do&lt;/STRONG&gt;&lt;/EM&gt; loops have no internal code.&amp;nbsp; They just have a stopping condition based on the date relationships you posted.&amp;nbsp; If none of the pre-existing links satisfy the stopping condition, then the index variable L will be exactly 1 greater than the prior _nlinks value - indicating need for a new link id.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Actually the _linkdates table in the program doesn't used dummy variables in the tables cells.&amp;nbsp; It uses date values.&lt;/P&gt;</description>
      <pubDate>Sun, 24 Apr 2022 21:37:54 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merging-Inexact-Dates-on-Range-with-Multiple-Observations/m-p/809516#M319240</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2022-04-24T21:37:54Z</dc:date>
    </item>
  </channel>
</rss>

