<?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: How to shorten my code without hardcoding? Date Manipulation in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748743#M235172</link>
    <description>&lt;P&gt;Here's a tutorial on using Arrays in SAS&lt;BR /&gt;&lt;A href="https://stats.idre.ucla.edu/sas/seminars/sas-arrays/" target="_blank"&gt;https://stats.idre.ucla.edu/sas/seminars/sas-arrays/&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Definitely need arrays and a data step.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you had a long format then SQL would actually work better but you don't so in this case, a data step would be more efficient.&lt;/P&gt;</description>
    <pubDate>Thu, 17 Jun 2021 19:01:21 GMT</pubDate>
    <dc:creator>Reeza</dc:creator>
    <dc:date>2021-06-17T19:01:21Z</dc:date>
    <item>
      <title>How to shorten my code without hardcoding? Date Manipulation</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748739#M235169</link>
      <description>&lt;P&gt;I need to compare multiple dates + inclusion/exclusion and hoping i can have a shorter code without hardcoding&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Must have one m1_dt and at least two dates "dt#" within 30 days after the start_dt&lt;/LI&gt;&lt;LI&gt;Must compare all date variables (dt1 to dt4) and identify if the dates were within 30 days&lt;/LI&gt;&lt;LI&gt;Exclusion Code =&amp;nbsp;'DDD','EEE','FFF&lt;/LI&gt;&lt;LI&gt;Identifiers&amp;nbsp;&lt;OL&gt;&lt;LI&gt;yes with exlusion code + 1m and at least 2 dt within 30 days&lt;/LI&gt;&lt;LI&gt;yes with 1m and at least 2 dt within 30 days&lt;/LI&gt;&lt;LI&gt;no with exclusion code&lt;/LI&gt;&lt;LI&gt;no without exclusion code&lt;/LI&gt;&lt;/OL&gt;&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Please run the code below to see the expected result&lt;/P&gt;&lt;PRE&gt;data dataset1;
input id $1-3 start_dt 4-12 m1_dt 13-21 dt1 22-30 dt1_code $31-34 dt2 35-43 dt2_code $44-47 dt3 48-56 dt3_code $57-60 dt4 61-69 dt4_code $70-73;
datalines;
911 20200401 20200410 20200408 AAA 20200426	AAA 20200504 EEE 20200603 EEE
912	20200401 20200411 20200409 AAA 20200426	AAA	20200506 AAA 20200508 BBB
913	20200401 20200409 20200408 BBB 20200426	CCC	20200504 EEE 20200506 EEE
914	20200401 20200423 20200421 BBB 20200422	CCC
915	20200401 20200410 20200408 DDD 20200426	DDD
916	20200401 20200410 20200408 DDD
917	20200401 20200410 20200408 AAA
918	20200401 20200410 20200408 CCC
;
run;

proc sql;
create table dataset2 as select distinct
id,		
input(put(start_dt,8.),yymmdd8.) as start_dt format mmddyy10.,	
input(put(m1_dt,8.),yymmdd8.) as m1_dt format mmddyy10.,
input(put(dt1,8.),yymmdd8.) as dt1 format mmddyy10.,	
dt1_code,
input(put(dt2,8.),yymmdd8.) as dt2 format mmddyy10.,		
dt2_code,	
input(put(dt3,8.),yymmdd8.) as dt3 format mmddyy10.,	
dt3_code,	
input(put(dt4,8.),yymmdd8.) as dt4 format mmddyy10.,
dt4_code
from dataset1; quit;

%let exlude=('DDD','EEE','FFF');

/*expected result*/
proc sql;
create table expected_result as select distinct
a.*
,case when ((m1_dt is not null and (m1_dt-start_dt)&amp;lt;=30) 
and (((dt1 is not null and (dt1-start_dt)&amp;lt;=30) and (dt2 is not null and (dt2-start_dt)&amp;lt;=30) and 
	(dt3 is not null and (dt3-start_dt)&amp;lt;=30) and (dt4 is not null and (dt4-start_dt)&amp;lt;=30)) or 

	((dt1 is not null and (dt1-start_dt)&amp;lt;=30) and (dt2 is not null and (dt2-start_dt)&amp;lt;=30) and 
	(dt3 is not null and (dt3-start_dt)&amp;lt;=30)) or 

	((dt1 is not null and (dt1-start_dt)&amp;lt;=30) and (dt2 is not null and (dt2-start_dt)&amp;lt;=30)))
and (dt1_code not in &amp;amp;exlude. and dt2_code not in &amp;amp;exlude. and dt3_code not in &amp;amp;exlude. and dt4_code not in &amp;amp;exlude.)) 
then 'yes with 1m and at least 2 dt within 30 days' 

when ((m1_dt is not null and (m1_dt-start_dt)&amp;lt;=30) 
and (((dt1 is not null and (dt1-start_dt)&amp;lt;=30) and (dt2 is not null and (dt2-start_dt)&amp;lt;=30) and 
	(dt3 is not null and (dt3-start_dt)&amp;lt;=30) and (dt4 is not null and (dt4-start_dt)&amp;lt;=30)) or 

	((dt1 is not null and (dt1-start_dt)&amp;lt;=30) and (dt2 is not null and (dt2-start_dt)&amp;lt;=30) and 
	(dt3 is not null and (dt3-start_dt)&amp;lt;=30)) or 

	((dt1 is not null and (dt1-start_dt)&amp;lt;=30) and (dt2 is not null and (dt2-start_dt)&amp;lt;=30)))
and (dt1_code in &amp;amp;exlude. or dt2_code in &amp;amp;exlude. or dt3_code in &amp;amp;exlude. or dt4_code in &amp;amp;exlude.)) 
then 'yes with exclusion code + 1m and at least 2 dt within 30 days'

when (dt1_code in &amp;amp;exlude. or dt2_code in &amp;amp;exlude. or dt3_code in &amp;amp;exlude. or dt4_code in &amp;amp;exlude.) 
then 'no with exclusion code'

when (dt1_code not in &amp;amp;exlude. and dt2_code not in &amp;amp;exlude. and dt3_code not in &amp;amp;exlude. and dt4_code not in &amp;amp;exlude.) 
then 'no without exclusion code'
else 'no' end as identifier
from dataset2 a;quit;

&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 17 Jun 2021 17:56:36 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748739#M235169</guid>
      <dc:creator>annaleticia</dc:creator>
      <dc:date>2021-06-17T17:56:36Z</dc:date>
    </item>
    <item>
      <title>Re: How to shorten my code without hardcoding? Date Manipulation</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748742#M235171</link>
      <description>&lt;P&gt;I have to admit, I'm not going to dig through this entire mass of code to see where it can be simplified.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I will throw out my gut feeling that if you do this in a DATA step rather than SQL, then you have the feature called ARRAY and then it doesn't matter how many dtxxx variables you have, you can handle them all in an ARRAY, you program it one time and loop through. No hardcoding. You also can use the WHICHC function to search across all the dtxxx variables.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Another thought is always &lt;A href="https://communities.sas.com/t5/SAS-Communities-Library/Maxims-of-Maximally-Efficient-SAS-Programmers/ta-p/352068" target="_self"&gt;Maxim 19&lt;/A&gt;, "Long beats Wide", which means instead of having dt1 through dt4 on one row, you have separate rows with an indetifier 1 through xxx, and a variable dt. This can greatly simplify your programming and again lets you avoid hard-coding stuff. There are many many examples of Long beats Wide here in the SAS Communities.&lt;/P&gt;</description>
      <pubDate>Thu, 17 Jun 2021 19:00:45 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748742#M235171</guid>
      <dc:creator>PaigeMiller</dc:creator>
      <dc:date>2021-06-17T19:00:45Z</dc:date>
    </item>
    <item>
      <title>Re: How to shorten my code without hardcoding? Date Manipulation</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748743#M235172</link>
      <description>&lt;P&gt;Here's a tutorial on using Arrays in SAS&lt;BR /&gt;&lt;A href="https://stats.idre.ucla.edu/sas/seminars/sas-arrays/" target="_blank"&gt;https://stats.idre.ucla.edu/sas/seminars/sas-arrays/&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Definitely need arrays and a data step.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you had a long format then SQL would actually work better but you don't so in this case, a data step would be more efficient.&lt;/P&gt;</description>
      <pubDate>Thu, 17 Jun 2021 19:01:21 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748743#M235172</guid>
      <dc:creator>Reeza</dc:creator>
      <dc:date>2021-06-17T19:01:21Z</dc:date>
    </item>
    <item>
      <title>Re: How to shorten my code without hardcoding? Date Manipulation</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748746#M235175</link>
      <description>&lt;P&gt;First question would be why are your "date" variables not already date values?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;What does m1_dt, dt1 and dt2 (etc) names actually mean. It may give us a clue to better file structure.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You really don't provide much in the way of what seems "right" for the data but this may give you a clue to one way to get a count of days less within 30:&lt;/P&gt;
&lt;PRE&gt;data example;
   input a x y z;
   count= sum( 0 le x-a le 30,0 le y-a le 30,0 le z-a le 30);
datalines;
25 29 45 60
25 .  45 60
25 .  .  60
25 69 65 60
25 29 .  60
;&lt;/PRE&gt;
&lt;P&gt;This sort of works because each comparison will return a value of 1 or 0. Then sums those.&lt;/P&gt;
&lt;P&gt;Comment on "within": Typically I would expect an ABSOLUTE value for something like (x-y) to get the actual interval. You are only testing that startdate is less than 30 days prior to dt. So I is there something in your data you have not stated that says dt1 and such are only larger than startdate when present???&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Since SAS date values are integer numbers of days you can test if a group of variables "are within 30 days" with the Range function:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;if range(dt1,dt2,dt3,dt4) le 30 then &amp;lt;whatever&amp;gt;. This will ignore missing values .&lt;/P&gt;
&lt;P&gt;The range function is the result of the largest value subtracting the smallest.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Your exclusion and identifier comments aren't very clear.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I also don't see anything in this that really suggests SQL is a better solution than a data step.&lt;/P&gt;</description>
      <pubDate>Thu, 17 Jun 2021 19:32:03 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748746#M235175</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2021-06-17T19:32:03Z</dc:date>
    </item>
    <item>
      <title>Re: How to shorten my code without hardcoding? Date Manipulation</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748761#M235182</link>
      <description>&lt;P&gt;So as long as the ID has one m1_dt&amp;nbsp; and at least two dt# within 30 days after the start_dt.&lt;/P&gt;&lt;P&gt;I'm using the exclusion list&amp;nbsp;&amp;nbsp;('DDD','EEE','FFF') to separate or flag the ids "see the identifier column below"&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;yes &lt;U&gt;with exclusion code&lt;/U&gt; + 1m and at least 2 dt within 30 days&lt;/LI&gt;&lt;LI&gt;yes with 1m and at least 2 dt within 30 days&lt;/LI&gt;&lt;LI&gt;no &lt;U&gt;with exclusion&lt;/U&gt; code&lt;/LI&gt;&lt;LI&gt;no without exclusion code&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;Expected result:&lt;/P&gt;&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="annaleticia_1-1623960404424.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/60451i48451084667D6252/image-size/medium?v=v2&amp;amp;px=400" role="button" title="annaleticia_1-1623960404424.png" alt="annaleticia_1-1623960404424.png" /&gt;&lt;/span&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 17 Jun 2021 20:07:06 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748761#M235182</guid>
      <dc:creator>annaleticia</dc:creator>
      <dc:date>2021-06-17T20:07:06Z</dc:date>
    </item>
    <item>
      <title>Re: How to shorten my code without hardcoding? Date Manipulation</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748782#M235195</link>
      <description>&lt;P&gt;Below code returns the same result than your desired SQL.&lt;/P&gt;
&lt;P&gt;I've converted your case statements to data step logic - and while doing this realized that due to the OR conditions you actually only need to check the day differences for variables dt1 and dt2. ...not sure if that's what you've intended to do - but it's not changing the logic you've provided.&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
  infile datalines dsd dlm=' ' truncover;
  input 
    @1 id $3. 
    @5 start_dt yymmdd8. 
    @14 m1_dt yymmdd8.
    @23 dt1 yymmdd8.
    @32 dt1_code $3. 
    @36 dt2 yymmdd8.
    @45 dt2_code $3. 
    @49 dt3 yymmdd8.
    @58 dt3_code $3.
    @62 dt4 yymmdd8.
    @71 dt4_code $3.
    ;
  format start_dt m1_dt dt1-dt4 date9.;
  datalines;
911 20200401 20200410 20200408 AAA 20200426 AAA 20200504 EEE 20200603 EEE
912 20200401 20200411 20200409 AAA 20200426 AAA 20200506 AAA 20200508 BBB
913 20200401 20200409 20200408 BBB 20200426 CCC 20200504 EEE 20200506 EEE
914 20200401 20200423 20200421 BBB 20200422 CCC
915 20200401 20200410 20200408 DDD 20200426 DDD
916 20200401 20200410 20200408 DDD
917 20200401 20200410 20200408 AAA
918 20200401 20200410 20200408 CCC
;

proc format;
  value case
    1='yes with 1m and at least 2 dt within 30 days'
    2='yes with exclusion code + 1m and at least 2 dt within 30 days'
    3='no with exclusion code'
    4='no without exclusion code'
    5='no'
    ;
run;

%let exclude=('DDD','EEE','FFF');
data want;
  set have;
  _dt_code_flg= (
                  dt1_code in &amp;amp;exclude or
                  dt2_code in &amp;amp;exclude or
                  dt3_code in &amp;amp;exclude or
                  dt4_code in &amp;amp;exclude 
                );

  if 
    .&amp;lt;m1_dt-start_dt&amp;lt;=30  and
    (
/*      .&amp;lt;dt1-start_dt&amp;lt;=30    and*/
/*      .&amp;lt;dt2-start_dt&amp;lt;=30    and*/
/*      .&amp;lt;dt3-start_dt&amp;lt;=30    and*/
/*      .&amp;lt;dt4-start_dt&amp;lt;=30   */
/*      or*/
/*      .&amp;lt;dt1-start_dt&amp;lt;=30    and*/
/*      .&amp;lt;dt2-start_dt&amp;lt;=30    and*/
/*      .&amp;lt;dt3-start_dt&amp;lt;=30   */
/*      or*/
      .&amp;lt;dt1-start_dt&amp;lt;=30    and
      .&amp;lt;dt2-start_dt&amp;lt;=30    
    )
    then
    do;
      if _dt_code_flg=0 then case=1;
      else
      if _dt_code_flg=1 then case=2;
    end;

  else
  if _dt_code_flg=1 then case=3;

  else
  if _dt_code_flg=0 then case=4;

  else
    case=5;

  identifier=put(case,case. -l);
  drop case _dt_code_flg;
run;
&lt;/CODE&gt;&lt;/PRE&gt;</description>
      <pubDate>Thu, 17 Jun 2021 21:44:13 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748782#M235195</guid>
      <dc:creator>Patrick</dc:creator>
      <dc:date>2021-06-17T21:44:13Z</dc:date>
    </item>
    <item>
      <title>Re: How to shorten my code without hardcoding? Date Manipulation</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748797#M235209</link>
      <description>&lt;P&gt;1. Why not use the informat when reading the cards data rather than create dataset2?&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;2. This&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;(((dt1 is not null and (dt1-start_dt)&amp;lt;=30) and (dt2 is not null and (dt2-start_dt)&amp;lt;=30) and (dt3 is not null and (dt3-start_dt)&amp;lt;=30) and (dt4 is not null and (dt4-start_dt)&amp;lt;=30)) or &lt;BR /&gt;((dt1 is not null and (dt1-start_dt)&amp;lt;=30) and (dt2 is not null and (dt2-start_dt)&amp;lt;=30) and (dt3 is not null and (dt3-start_dt)&amp;lt;=30)) or &lt;BR /&gt;((dt1 is not null and (dt1-start_dt)&amp;lt;=30) and (dt2 is not null and (dt2-start_dt)&amp;lt;=30))&lt;BR /&gt;)&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;is the same as&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;((dt1 is not null and (dt1-start_dt)&amp;lt;=30) and (dt2 is not null and (dt2-start_dt)&amp;lt;=30))&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;3. Not identical, but you might want to write&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;. &amp;lt; dt1-start_dt &amp;lt;=30&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;instead of&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;dt1 is not null and (dt1-start_dt)&amp;lt;=30)&lt;/P&gt;
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 17 Jun 2021 23:36:54 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748797#M235209</guid>
      <dc:creator>ChrisNZ</dc:creator>
      <dc:date>2021-06-17T23:36:54Z</dc:date>
    </item>
    <item>
      <title>Re: How to shorten my code without hardcoding? Date Manipulation</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748811#M235220</link>
      <description>&lt;P&gt;Thank you. This is so helpful&lt;/P&gt;</description>
      <pubDate>Fri, 18 Jun 2021 02:21:00 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-shorten-my-code-without-hardcoding-Date-Manipulation/m-p/748811#M235220</guid>
      <dc:creator>annaleticia</dc:creator>
      <dc:date>2021-06-18T02:21:00Z</dc:date>
    </item>
  </channel>
</rss>

