<?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>mkeintz Tracker</title>
    <link>https://communities.sas.com/kntur85557/tracker</link>
    <description>mkeintz Tracker</description>
    <pubDate>Sat, 09 May 2026 20:47:41 GMT</pubDate>
    <dc:date>2026-05-09T20:47:41Z</dc:date>
    <item>
      <title>Re: Max per loan in last 7 days</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Max-per-loan-in-last-7-days/m-p/974704#M377965</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159549"&gt;@Ronein&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;Why array have 6 arguments?&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;The array does NOT have six elements, it has seven elements, where the lower bound is zero (not one) and the upper bound is six.&amp;nbsp; When you divide the date value by 7 and keep the remainder, you will end up with 0, 1, ..., 5, or 6.&amp;nbsp; So each day of the week can trivially be placed in exactly one element of the array.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 10 Sep 2025 03:19:02 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Max-per-loan-in-last-7-days/m-p/974704#M377965</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-09-10T03:19:02Z</dc:date>
    </item>
    <item>
      <title>Re: Max per loan in last 7 days</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Max-per-loan-in-last-7-days/m-p/974398#M377902</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159549"&gt;@Ronein&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;Why array have 30000 arguments? How dud you know to choose this number ?&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;If you are using an array from 0 to 30000, it covers Jan 1, 1960 through 19feb2024.&amp;nbsp; You can customize the date range per below (say for 01jan2009 through 31dec2020):&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;%let begdate=01jan2009 ;
%let enddate=31dec2020 ;

data;
  * other sas code ;
  array history {%sysevalf("&amp;amp;begdate"d):%sysevalf("&amp;amp;enddate"d)} _temporary_ ;
  * other sas code ;
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Mon, 08 Sep 2025 11:08:19 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Max-per-loan-in-last-7-days/m-p/974398#M377902</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-09-08T11:08:19Z</dc:date>
    </item>
    <item>
      <title>Re: Max per loan in last 7 days</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Max-per-loan-in-last-7-days/m-p/974348#M377891</link>
      <description>&lt;P&gt;Here's a data step that effectively maintains a moving window of offer amounts for the prior 7 days.&lt;BR /&gt;&amp;nbsp; With each obs, first weed out stale (over 7 days prior) data.&lt;/P&gt;
&lt;P&gt;&amp;nbsp; Then just take the maximum of that small array.&lt;/P&gt;
&lt;P&gt;&amp;nbsp; Then update the arrays with the new obs&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
  format date ddmmyy10.;
  input custid date :date9. loansAmnt offerAmnt;
cards;
111 01JUL2025 .     50000
111 03jul2025 .     22000
111 08jul2025 .     19000
111 09jul2025 5000  .
222 01jul2025 .     40000
222 03jul2025 .     28000
222 04jul2025 13000 .
222 08jul2025 .     27000
223 09jul2025 35000 .
run;
data want (drop=_:);
  set have;
  by custid;

  array tempdat{0:6} _temporary_; /*Observed dates within prior 7 days*/
  array tempval{0:6} _temporary_; /*Observed offers within prior 7 days*/  

  /* Weed stale data first */
  if first.custid=1 then call missing(of tempval{*},of tempdat{*});
  else do while (.&amp;lt; min(of tempdat{*}) &amp;lt; date-7);    
    _d=mod(min(of tempdat{*}),7);
    call missing(tempval{_d},tempdat{_d});
  end;

  /* Get the maximum */
  if n(of tempdat{*})&amp;gt;0 then max_prior_7days=max(of tempval{*});

  /*Update the arrays with current obs */
  _d=mod(date,7);   
  tempdat{_d}=date;
  tempval{_d}=offeramnt;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Ignore the previously sumitted code below, which didn't weed before taking the maximum:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;data want (drop=_:);&lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp; set have; by custid; &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp; array tempdat{0:6} _temporary_; /*Observed dates within prior 7 days*/ &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp; array tempval{0:6} _temporary_; /*Observed offers within prior 7 days*/ &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp; /* Get the maximum, when there is a 7-day window available */ &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp; if first.custid=0 and dif(date)&amp;lt;=7 then max_prior_7days=max(of tempval{*}); &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp; else call missing(of tempval{*},of tempdat{*}); &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp; /*Update the arrays with current obs */ &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp; _d=mod(date,7); tempdat{_d}=date; &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp; tempval{_d}=offeramnt; &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp; /*Weed out stale data */ &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp; do while (min(of tempdat{*})&amp;lt;date-7); &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; _d=mod(min(of tempdat{*}),7); &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; call missing(tempval{_d},tempdat{_d}); &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;&amp;nbsp; end; &lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&lt;STRIKE&gt;run;&lt;/STRIKE&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Two points:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;The temporary arrays are indexed from 0 to 6, effectively representing a day-of-week index.&amp;nbsp; So the data in the arrays are not ordered strictly chronologically, but order doesn't matter for getting the maximum.&amp;nbsp; The task is to be sure to eliminate stale values.&lt;/LI&gt;
&lt;LI&gt;The DIF(x) function is&amp;nbsp;&amp;nbsp; x-lag(x).&lt;/LI&gt;
&lt;/OL&gt;</description>
      <pubDate>Sun, 07 Sep 2025 20:49:58 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Max-per-loan-in-last-7-days/m-p/974348#M377891</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-09-07T20:49:58Z</dc:date>
    </item>
    <item>
      <title>Re: Proc SQL</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Proc-SQL/m-p/974175#M377829</link>
      <description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;An interviewer insisting on PROC SQL code for the 3rd highest value is not attempting to assess your SAS expertise.&lt;/P&gt;</description>
      <pubDate>Fri, 05 Sep 2025 01:16:18 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Proc-SQL/m-p/974175#M377829</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-09-05T01:16:18Z</dc:date>
    </item>
    <item>
      <title>Re: PROC SQL match missing about 3% of cases even though they are in both files</title>
      <link>https://communities.sas.com/t5/SAS-Programming/PROC-SQL-match-missing-about-3-of-cases-even-though-they-are-in/m-p/973469#M377694</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/43822"&gt;@Wolverine&lt;/a&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Glad you identified the problem.&amp;nbsp; Mark your own explanation as the solution, so that this topic no longer appears as unsolved.&lt;/P&gt;</description>
      <pubDate>Thu, 28 Aug 2025 00:52:21 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/PROC-SQL-match-missing-about-3-of-cases-even-though-they-are-in/m-p/973469#M377694</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-08-28T00:52:21Z</dc:date>
    </item>
    <item>
      <title>Re: Extracting all records that share variable 2 values, where at least one variable 1 value is = XX</title>
      <link>https://communities.sas.com/t5/New-SAS-User/Extracting-all-records-that-share-variable-2-values-where-at/m-p/971284#M43408</link>
      <description>&lt;P&gt;If the dataset is not particularly big, then I think your best option is the hash object technique suggested by&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/12447"&gt;@Patrick&lt;/a&gt;. The code is simple.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;That solution requires reading the data in two unsynchronized data streams, which could create a performance hit in the case of large datasets, due to disk activity.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Now if the data were sorted by VAR2, you could do:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want;
  merge have (where=(var1='XX')  in=wanted) 
        have;
  by var2;
  if wanted;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;which synchronizes the data streams and reduces disk activity.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Your data are not sorted by VAR2, although it is grouped by VAR2.&amp;nbsp; So you can generate data stream synchronization with code such as this:&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 (where=(var1='XX') rename=(var2=_var2));

  do until (last.var2=1 and var2=_var2);
    set have;
    by var2 notsorted;
    if var2=_var2 then output; 
  end;
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The above assumes no more than one var1='XX' for any given VAR2.&amp;nbsp; If you can have two or more var1='XX' cases, then:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want (drop=_:);
  set have (where=(var1='XX') rename=(var2=_var2));
  by _var2 notsorted;

  if last._var2 then do until (last.var2=1 and var2=_var2);
    set have;
    by var2 notsorted;
    if var2=_var2 then output; 
  end;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;And yes, the degree of synchronization achieved would depend on the distribution of the "XX" cases.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 22 Jul 2025 13:56:26 GMT</pubDate>
      <guid>https://communities.sas.com/t5/New-SAS-User/Extracting-all-records-that-share-variable-2-values-where-at/m-p/971284#M43408</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-07-22T13:56:26Z</dc:date>
    </item>
    <item>
      <title>Re: Identify patterns across observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Identify-patterns-across-observations/m-p/971148#M377259</link>
      <description>&lt;OL&gt;
&lt;LI&gt;First, I assume that flag1 is based on the type variable, and flag2 is based on the type2 variable, correct?&lt;BR /&gt;&lt;BR /&gt;&lt;/LI&gt;
&lt;LI&gt;Next: y&lt;SPAN&gt;ou have two observations for ID B with type='99'.&amp;nbsp; They are separated by two observations with type='11' and type='1'.&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;&lt;/SPAN&gt;So why have you assigned flag1=0 to those 99's, given they are NOT separated by a 10 or a 4, which I understand is the only reason to set flag1 to 0?&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;If I understand you correctly, and if my conjecture about ID=B is correct, then you can use the following code:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want (drop=_: nxt:);
  do _n=1 by 1 until (last.id);
    set   have;
    by id;
    array _chk{30};
    if type='99' then do;
      if _last99^=. then do;
        _chk{_last99}=1; 
        _chk{_n}=1;
      end;
      _last99=_n;
    end;
    if type in ('10','4') then _last99=.;
    if type2=0 then _last_t2_eq_0_date=date;
  end;

  /* With the _chk array and _last_t2_eq_0_date in hand, reread this ID and set flags*/
  do _p=1 to _n;
    merge have
          have (firstobs=2 keep=id type2 rename=(id=nxt1_id type2=nxt1_t2))
          have (firstobs=3 keep=id type2 rename=(id=nxt2_id type2=nxt2_t2));
    if type='99' then flag1=sum(0,_chk{_p});
    else flag1=.;

    if id=nxt2_id and type2=2 and nxt1_t2=1 and nxt2_t2=0 then flag2=1;
    else flag2=.;
    if flag2=1 then date2=_last_t2_eq_0_date;
    else date2=.;
    output;
  end;
  format date2 date9. ;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;It reads each ID twice.&amp;nbsp; the first time it checks for type='99' that are not separated by '4' or '10', and set dummies in the _CHK array accordingly.&amp;nbsp; It also keeps track of the last date for type2=0.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In the second pass of data, the flags are set, using the array for flag1.&amp;nbsp; For flag2 the second pass uses the firstobs= options in a MERGE statement to look ahead for a pattern of type2=2 for current, followed by a type2=1 and type2=0.&amp;nbsp; Note the MERGE must NOT use a BY ID statement.&amp;nbsp; If it did, then the alignment set up by the FIRSTOBS parameters would be lost at the beginning of the second ID.&lt;/P&gt;</description>
      <pubDate>Sat, 19 Jul 2025 22:39:00 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Identify-patterns-across-observations/m-p/971148#M377259</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-07-19T22:39:00Z</dc:date>
    </item>
    <item>
      <title>Re: Sorting data within the cell</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Sorting-data-within-the-cell/m-p/970637#M377117</link>
      <description>&lt;P&gt;You can transfer the components of the cell into a hash object with the "ordered" attribute.&amp;nbsp; Then iterate through them and concatenate each of them:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
  input col1 col2 :$50. ;
cards;
1 1,5,4,3,2,6,3.5
2 21,3,2,1,5,15,17,3
3 1,2,3
4 4,3,2
5 1,2,junk,3
;

data want (drop=i _:);
  set have;
  if _n_=1 then do;
    declare hash h (ordered:'A',multidata:'Y');
      h.definekey('_x');
      h.definedata('_x');
      h.definedone();
    declare hiter hi ('h');
  end;

  do i=1 to countw(col2,',');
    _x=input(scan(col2,i,','),best12.);
    if _x^=. then h.add();
  end;
  length new_col $50;
  do while (hi.next()=0);
    new_col=catx(',',new_col,_x);
  end;
  h.clear();
run;
  &lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Sat, 12 Jul 2025 02:42:01 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Sorting-data-within-the-cell/m-p/970637#M377117</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-07-12T02:42:01Z</dc:date>
    </item>
    <item>
      <title>Re: Search  var with best match name</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Search-var-with-best-match-name/m-p/970575#M377094</link>
      <description>&lt;P&gt;What if you want to find the closest match to X145, from a list of variables named X14,X15,X125,X147.X345,X545?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;As&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/10892"&gt;@PaigeMiller&lt;/a&gt;&amp;nbsp;has said, would the use of spelling distance have any utility at all in this case?&lt;/P&gt;</description>
      <pubDate>Thu, 10 Jul 2025 23:37:33 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Search-var-with-best-match-name/m-p/970575#M377094</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-07-10T23:37:33Z</dc:date>
    </item>
    <item>
      <title>Re: convert numeric to char</title>
      <link>https://communities.sas.com/t5/SAS-Programming/convert-numeric-to-char/m-p/970275#M377058</link>
      <description>&lt;P&gt;If you change&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;z_char=put(z,best.);&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;to&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;z_char=put(z,8.2);&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;then z_char will display what you want.&amp;nbsp; Assuming this statement is the first reference to z_char, it will be an 8-byte character variable.&amp;nbsp; It will also be right justified, and with two decimal places.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You may not want it to be right justified, in which case, you can use&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;z_char=left(put(z,8.2));&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;But remember that if you left justify the character value, then sorting by z_char may not generate the same order as sorting by z (i.e. '11.18&amp;nbsp; &amp;nbsp;' would precede '6.18&amp;nbsp; &amp;nbsp; ').&lt;/P&gt;
&lt;P&gt;--- Lexicographic ordering.&lt;/P&gt;</description>
      <pubDate>Mon, 07 Jul 2025 14:42:52 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/convert-numeric-to-char/m-p/970275#M377058</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-07-07T14:42:52Z</dc:date>
    </item>
    <item>
      <title>Re: set data sets  with customers in pop table only</title>
      <link>https://communities.sas.com/t5/SAS-Programming/set-data-sets-with-customers-in-pop-table-only/m-p/970038#M376993</link>
      <description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If each dataset is sorted by ID, then&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want (drop=_:);
  set t1 (in=in1) t2 t3;
  by id;
  retain _found_in_t1;
  if first.id then _found_in_t1=in1;
  if _found_in_t1;
run;&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Tue, 01 Jul 2025 16:08:57 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/set-data-sets-with-customers-in-pop-table-only/m-p/970038#M376993</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-07-01T16:08:57Z</dc:date>
    </item>
    <item>
      <title>Re: How to Randomly Pick a Value from Other Table</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-Randomly-Pick-a-Value-from-Other-Table/m-p/970012#M376988</link>
      <description>&lt;P&gt;You have a small dataset of phone numbers by state, and a "large" dataset of accounts.&amp;nbsp; I understand that you are fine with randomly assigning a given phone number to multiple qualifying accounts.&amp;nbsp; Here's a program that avoids the need to sort the large dataset just to facilitate a merge:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Using&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/18408"&gt;@Ksharp&lt;/a&gt;'s sample data:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data phone_arrays (keep=state _nphones _col:);
  do _nphones=1 by 1 until (last.state);
    set tablea  (where=(not missing(phone)));
    by state;
    array _col {50};
    _col{_nphones}=phone;
  end;
run;

data want (drop=_:);
  set tableb;
  if _n_=1 then do;
    if 0 then set phone_arrays ;
    declare hash h (dataset:'phone_arrays');
      h.definekey('state'); 
      h.definedata(all:'Y');
      h.definedone();
  end;
  array col {*} _col: ;
  
  if h.find()=0 then phnum=col{ceil(_nphones*ranuni(1508915))};
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;The _COL array is given an arbitrary size -- large enough to account for the largest group of available phone numbers.&lt;/P&gt;
&lt;P&gt;This assumes the TABLEA dataset is already sorted by state.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 01 Jul 2025 00:49:02 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-Randomly-Pick-a-Value-from-Other-Table/m-p/970012#M376988</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-07-01T00:49:02Z</dc:date>
    </item>
    <item>
      <title>Re: How to sort and restrict a big dataset</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-sort-and-restrict-a-big-dataset/m-p/969822#M376953</link>
      <description>&lt;P&gt;The PROC SUMMARY offers a neat compact single-pass solution.&amp;nbsp; It will certainly use a lot less disk input/output resources than the PROC SORT solution, and will probably be a lot faster - assuming there is no memory constraint.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;BUT ... does your data have the possibility of tied maximum time_flag values for a given ID/VAR1/VAR2?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If not, then ignore the rest of this comment.&amp;nbsp;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But if it does, then the PROC SUMMARY might not likely give the same result as the PROC SORT ... if LAST.VAR2 solution.&amp;nbsp; It will choose different records (with possibly different VAR3/VAR4 values) among the tied records.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This is because the default behavior of PROC SORT is to preserve the original order (from the unsorted dataset) of tied records.&amp;nbsp; So that solution would always choose the latest of the tied records.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;A quick test of PROC SUMMARY with ties suggests it would always choose the first of such ties.&amp;nbsp; At least it did so in the test below:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data ties;
  set sashelp.class (keep=name sex age weight);
  order='First'; output;
  order='Last' ; output;
run;
proc summary nway data=ties;
  class sex age;
  output out=summ_want (drop=_:) idgroup (max(weight) out (name weight order)=);
run;
proc sort data=ties;
  by sex age weight;
run;
data sort_want;
  set ties;
  by sex age;
  if last.age;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Dataset summ_want has order='First' in every output record, but the PROC SORT approach always has ORDER='Last'.&lt;/P&gt;</description>
      <pubDate>Fri, 27 Jun 2025 00:14:07 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-sort-and-restrict-a-big-dataset/m-p/969822#M376953</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-06-27T00:14:07Z</dc:date>
    </item>
    <item>
      <title>Re: Need to create JOIN variable for OVERLAPPING AEs</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Need-to-create-JOIN-variable-for-OVERLAPPING-AEs/m-p/969669#M376913</link>
      <description>&lt;P&gt;If I understand your request correctly, then:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data test;
    infile datalines truncover;
    input usubjid $3. aestdtc :$10. @17 aendt date7. ae &amp;amp; :$200.;
    format   aendt date9.;
datalines;
101 2024-12-18  28JAN25 Appetite lost
101 2024-12-19  26DEC24 Constipation
101 2024-12-30  10FEB25 Thrombopenia
101 2025-01-06  07FEB25 Neutropenia
101 2025-01-27  07FEB25 Neutropenia
101 2025-01-13  23MAR25 Anemia
101 2025-02-10  23MAR25 Anemia
101 2025-01-25  10FEB25 Dizziness
101 2025-01-25  10FEB25 Dyspnea
101 2025-01-25  .       Fatigue
101 2025-01-27  31JAN25 Nausea
101 2025-01-27  31JAN25 WBC decreased
101 2025-02-03  15FEB25 Rhinitis
101 2025-03-01  .       Epigastralgia
101 2025-03-01  03MAR25 Nausea
101 2025-03-01  03MAR25 Vomiting
101 2025-03-24  .       Anemia
101 2025-03-24  .       Thrombopenia
run;

DATA WANT;
  SET test;
  by usubjid ae notsorted;
  astdt=input(aestdtc,yymmdd10.);
  format astdt date9.;
  if astdt&amp;gt;lag(aendt) or first.ae=1 then join+1;
  if first.usubjid=1 then join=1;
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Do you have instances of a given AE qualifying to be assigned the same JOIN value, but occurring in non-consecutive observations?&amp;nbsp; If so, this code would need to be modified.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Note the BY statement allows detection of whenever a new AE description occurs (first.ae=1).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Also please provide your sample data in a &lt;EM&gt;&lt;STRONG&gt;working data step&lt;/STRONG&gt;&lt;/EM&gt;.&amp;nbsp;For example, your informat of date9. for aendt should have been date7.&lt;/P&gt;</description>
      <pubDate>Wed, 25 Jun 2025 14:48:34 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Need-to-create-JOIN-variable-for-OVERLAPPING-AEs/m-p/969669#M376913</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-06-25T14:48:34Z</dc:date>
    </item>
    <item>
      <title>Re: Merge/join using a date from one dataset within a date range in another</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Merge-join-using-a-date-from-one-dataset-within-a-date-range-in/m-p/969567#M376876</link>
      <description>&lt;P&gt;This is a good use case for applying conditional SET statements in a data step.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Assuming:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;SET1 is sorted by ID/d_start/b/c/d&lt;/LI&gt;
&lt;LI&gt;SET1 has no instances of overlapping d_start-d_end date ranges&lt;/LI&gt;
&lt;LI&gt;SET2 is sorted by ID/eventstart&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;then&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data set1;
    input id $ d_start :date9. d_end :date9.
          physcat $ a b c d e;
    format d_start d_end date9.;
    datalines;
s001 01JAN2020 31DEC2020 A 1 2 3 1 0
s001 01JAN2020 31DEC2020 A 1 3 3 1 0
s001 01JAN2021 31DEC2021 B 1 3 3 2 1
s002 01JUN2019 31MAY2020 A 2 1 2 1 1
s002 01JUN2020 31MAY2021 C 2 2 2 2 0
s003 01JAN2020 31DEC2022 B 1 3 4 1 0
run;


data set2;
input id $ eventstart :date9.;
format eventstart date9.;
datalines;
s001 15JUN2020
s001 20JUL2021
s002 15AUG2019
s002 01JUL2020
s003 01JAN2021
s003 01JAN2023
run;

data need /view=need  /*Keep lowest B C D for each ID/D_START*/;
  set set1;
  by id d_start b c d;
  if first.d;
run;

data want (drop=_:);
  set need (keep=id d_start in=in1 rename=(d_start=_ref_date))
      set2 (                in=in2 rename=(eventstart=_ref_date));
  by id _ref_date;

  retain _left_sentinel .;
  if in1 then set need ;
  retain _right_sentinel ' ';

  if in2 ;
  set set2;
  if first.id or eventstart&amp;gt;d_end then call missing(of _left_sentinel--_right_sentinel);
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;This will also accommodate multiple events within a date range.&lt;/P&gt;</description>
      <pubDate>Mon, 23 Jun 2025 19:23:52 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Merge-join-using-a-date-from-one-dataset-within-a-date-range-in/m-p/969567#M376876</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-06-23T19:23:52Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected Results from PROC SQL Left Join</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Unexpected-Results-from-PROC-SQL-Left-Join/m-p/968371#M376542</link>
      <description>&lt;P&gt;Not only is a missing value still a value that can be used as a key, as&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/11562"&gt;@Kurt_Bremser&lt;/a&gt;&amp;nbsp;says, but there are many other possible missing values.&amp;nbsp; There are the 26 values of .A,.B, .... .Z, and also ._ (dot underscore).&amp;nbsp; These can be used for special purposes, if you want.&amp;nbsp; I don't think users would want SAS to automatically assume that such values should be ignored by default, as if they "have no value" in database tasks, even if they are "ignored" in statistical analysis.&lt;/P&gt;</description>
      <pubDate>Sat, 07 Jun 2025 03:13:24 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Unexpected-Results-from-PROC-SQL-Left-Join/m-p/968371#M376542</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-06-07T03:13:24Z</dc:date>
    </item>
    <item>
      <title>Re: Unexpected Results from PROC SQL Left Join</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Unexpected-Results-from-PROC-SQL-Left-Join/m-p/968359#M376538</link>
      <description>&lt;P&gt;Your left join is generating a cartesian cross of instances of FORMID_FUP=. in both datasets if you have multiple instances of missing value in the LEFT dataset.&amp;nbsp; MERGE ... BY, on the other hand, does not do this.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;And since you suggest, in the case of NON-missing FORMID_FUP, that using MERGE ...; BY FORMID_FUP; yields what you want (and what you get) from the PROC SQL ... LEFT JOIN, then it must be that the LEFT dataset has exactly one record per non-missing FORMID_FUP value.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;My question is why do you want cases with missing FORMID_FUP?&amp;nbsp; Why not exclude those cases from the join?&amp;nbsp; ... As in (see the "where=" dataset name parameters below):&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql;
		create table fup_timing as
		select a.*,
				t.Procedure_Date as t_Proc_Date label = "Followup Timing:  Date Procedure from Proc Form",
				t.Schedule as t_ScheduleCat label = "Followup Timing: Standard vs. Specialized",
		from followup (where=(formid_fup^=.))             as a
		left join followup_timing (where=(formid_fup^=.)) as t
		on a.FormID_FUP= t.FormID_FUP;
	quit;&lt;/CODE&gt;&amp;nbsp;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 06 Jun 2025 20:15:57 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Unexpected-Results-from-PROC-SQL-Left-Join/m-p/968359#M376538</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-06-06T20:15:57Z</dc:date>
    </item>
    <item>
      <title>Re: how to generate sequence number in sql</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-generate-sequence-number-in-sql/m-p/967742#M376431</link>
      <description>&lt;P&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/475533"&gt;@Prashan&lt;/a&gt;&amp;nbsp;wrote:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;&lt;BR /&gt;Consider SASHELP.CARS dataset and give the sequence number for MAKE variable.&lt;BR /&gt;Ex:- in MAKE variable, I want sequence number for AUDI&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;... stuff deleted ...&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;that too only with PROC SQL, not with data step, I know how to do with data step.&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;I think there are three statements relevant to this problem.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&lt;EM&gt;&lt;STRONG&gt;There is NO way to reliably reproduce within-group physical sequence numbers in PROC SQL using supported tools.&lt;/STRONG&gt;&lt;/EM&gt;&amp;nbsp; &amp;nbsp;By "reliable" I mean reproducible with certainty.&amp;nbsp;&lt;BR /&gt;&lt;BR /&gt;&lt;/LI&gt;
&lt;LI&gt;And even if you were to use monotonic(), there is no way to reproduce the results you would get in a DATA step (see my other note) unless the data were already sorted by the grouping variable.&amp;nbsp; And the use of proc sql with monotonic() would require filtering the source dataset once for each group (i.e. 38 times in the case of MAKE from sashelp.cars).&amp;nbsp; A big waste of resources.&lt;BR /&gt;&lt;BR /&gt;&lt;/LI&gt;
&lt;LI&gt;But probably the most important advice is to resist the atavistic urge to use PROC SQL for a purpose that it is totally unsuited for.&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 30 May 2025 02:24:31 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-generate-sequence-number-in-sql/m-p/967742#M376431</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-05-30T02:24:31Z</dc:date>
    </item>
    <item>
      <title>Re: how to generate sequence number in sql</title>
      <link>https://communities.sas.com/t5/SAS-Programming/how-to-generate-sequence-number-in-sql/m-p/967727#M376425</link>
      <description>&lt;P&gt;But&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/466238"&gt;@dxiao2017&lt;/a&gt;&amp;nbsp;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The dataset example you are using is already sorted by SEX, as presented by the OP.&amp;nbsp; But that may be unlike most situations (and unlike sashelp.class which is the source of the data example, and is sorted by name, not by sex/name.).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Besides there is no need to sort the data by sex, merely to generate within-sex sequence numbers.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For instance:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want (drop=_:);
  set sashelp.class;
  _nm+(sex='M');
  _nf+(sex='F');
  sequence=ifn(sex='M',_nm,_nf);
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;And if one MUST use SQL, then the undocumented (read "unsupported") MONOTONIC() function (see &lt;A href="https://communities.sas.com/t5/SAS-Communities-Library/MONOTONIC-function-in-PROC-SQL/ta-p/475752" target="_self"&gt;MONOTONIC-function-in-PROC-SQL&lt;/A&gt;) can be used for each sex:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql;
  create table want as 
  select name, monotonic() as seq from sashelp.class where sex='M'
  union corr
  select name, monotonic() as seq from sashelp.class where sex='F'
  ;
quit;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;But note that data order in the case of PROC SQL will almost certainly not be the same as in the original data set.&amp;nbsp; And that the row order will actually change depending on the order of variables&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 29 May 2025 21:03:53 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/how-to-generate-sequence-number-in-sql/m-p/967727#M376425</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-05-29T21:03:53Z</dc:date>
    </item>
    <item>
      <title>Re: Guidance Needed: Merging Two SAS Datasets with Inconsistent Key Formats</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Guidance-Needed-Merging-Two-SAS-Datasets-with-Inconsistent-Key/m-p/967395#M376349</link>
      <description>&lt;P&gt;This can be done in a single data step that first reads DATASET1, stores it in a hash object (lookup table) with a lookup key created by modifying X (remove leading non-digits, shorten it to the last 5 digits if necessary, and remove leading zeroes.&amp;nbsp; This is followed by reading DATASET2, where X is similarly modified, and a lookup is performed to see whether it is in the hash object, from which the PRODUCT value is retrieved:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data dataset1 (label='x with 3 or 5 digits');
  infile datalines missover; 
  input product $4.  x :$20. ;
datalines;
via1 
via2 003
via3 014
via4 GA4
via5 GA015
via6 319
via7 23456
via8 10101010198765
run;

data dataset2;
  infile datalines ;
  input name $1.  x :$20. ;
datalines;
a 2
b 3
c 14
d 4
e 15
f GF319
g 23456
h 98765
run;

data want (drop=rc);;
  set   dataset1 (in=in1) dataset2 (in=in2);
  where x^='';
  if _n_=1 then do;
    declare hash d1 ();
      d1.definekey('x');
      d1.definedata('product');
      d1.definedone();
  end;

  x=substr(x,anydigit(x)); /*Remove leading non-digits*/
  if length(x)&amp;gt;5 then x=substr(x,length(x)-4);  /*If too long, take last 5 digits*/
 
  do while (x=:'0'); /* Strip leading zeroes*/
    x=substr(x,2);
  end;
  if in1=1 then d1.add();
  if in2;
  rc=d1.find();
run;
&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Sat, 24 May 2025 03:51:16 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Guidance-Needed-Merging-Two-SAS-Datasets-with-Inconsistent-Key/m-p/967395#M376349</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-05-24T03:51:16Z</dc:date>
    </item>
  </channel>
</rss>

