<?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: Multiple Date formats in a single Text string in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Multiple-Date-formats-in-a-single-Text-string/m-p/950039#M371554</link>
    <description>&lt;P&gt;I would back up and think about non-macro approaches to implementing this sort of range check.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The idea of having a dataset range checks is a good one.&amp;nbsp; When you have date values in a dataset, you want to store them is date values (numeric variables), not character.&amp;nbsp; So your data could be like:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;DATA HAVE;
INPUT MEMBERID : $20. DOB : MMDDYY10.;
Format DOB MMDDYY10.;
CARDS;
1111 1/12/2001
2222 2/11/2003
3333 3/11/2003
4444 1/13/2000
;run;

DATA RANGE_CHECK;
INPUT Check_Number Low_DT : mmddyy10. High_DT : mmddyy10.;
format Low_DT High_Dt mmddyy10. ;
CARDS;
1 3/1/2000 5/1/2001
2 1/2/2002 12/2/2003
;run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;BR /&gt;Note I removed the macro variables from the CARDS data.&amp;nbsp; That won't work. If you want to make this data dynamic, happy to discuss alternative approaches.&amp;nbsp; I also make Low_DT and High_DT numeric date variables, rather than character.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Once you have that data, there are lots of different way to implement the range check.&amp;nbsp; One would be to use PROC SQL.&amp;nbsp; Below will join every record in your data against every check, and output the records where DOB is in the range.&amp;nbsp; You'll get a note in your log that SAS is performing a Cartesian product.&amp;nbsp; In this case, four records from HAVE * 2 records in RANGE_CHECK would result in 8 records, which are then filtered.&amp;nbsp; If you have big data, the Cartesian product may be slow, but it's one way you could approach the problem.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql ;
  create table want as
  select b.check_number,a.memberid,a.dob
  from have as a
      ,range_check as b
  where b.low_dt&amp;lt;=a.dob&amp;lt;=b.high_dt
  ;
quit ;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you look on lexjansen.com (an archive of SAS papers written by users) and search for "range check", you'll find lots of different approaches to implementing checks like this.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Wed, 06 Nov 2024 15:34:55 GMT</pubDate>
    <dc:creator>Quentin</dc:creator>
    <dc:date>2024-11-06T15:34:55Z</dc:date>
    <item>
      <title>Multiple Date formats in a single Text string</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Multiple-Date-formats-in-a-single-Text-string/m-p/950031#M371549</link>
      <description>&lt;P&gt;Hello!&amp;nbsp; Still pretty new to SAS.&amp;nbsp; I have a table of Check Dates that I need to compare my dataset to.&amp;nbsp; The trick is, sometimes the dates refer to a hard coded Macro variable date, and sometimes they come in as MM/DD/YYYY.&amp;nbsp; Was wondering if there is a magic wand to convert all dates to a single date format so i can do my compare.&amp;nbsp; Hope that makes sense!&amp;nbsp; Here's what I have.&amp;nbsp; Everything works except the final proc sql's where, which is where I'm stuck.&amp;nbsp; It's also probably not the most elegant solution, but it's where I'm at right now.&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=""&gt;DATA HAVE;
INPUT MEMBERID : $20. DOB : MMDDYY10.;
Format DOB MMDDYY10.;
CARDS;
1111 1/12/2001
2222 2/11/2003
3333 3/11/2003
4444 1/13/2000
;run;

DATA RANGE_CHECK;
INPUT Check_Number Low_DT : $50. High_DT : $50.;
CARDS;
1 3/1/2000 5/1/2001
2 &amp;amp;Hardcode_High_DT. &amp;amp;Hardcode_High_DT.
;run;


DATA FINAL_TABLE;
	format Check_Number 8.;
	format MEMBERID		$20.;
	format DOB 		 	MMDDYY10.;
;run;

%macro FindRanges();

 %let Hardcode_Low_DT = 02JAN2002;
 %let Hardcode_High_DT = 02DEC2003;


    proc sql  ;
           SELECT  Check_Number, 
                   quote(strip(resolve(Low_DT))), 
                   quote(strip(resolve(High_DT))) into 
			          :Check_Number_List separated by ' ',
			          :Low_DT_List separated by ';',
				      :High_DT_List separated by ';'
    		    FROM RANGE_CHECK;
				%let Check_Count =&amp;amp;sqlobs;
    ;quit;


  %do t = 1 %to &amp;amp;Check_Count.;

     %let Check_Number_Value = %scan(&amp;amp;Check_Number_List, &amp;amp;t);
     %let Low_Value = %scan(&amp;amp;Low_DT_List, &amp;amp;t, ';');   &lt;STRONG&gt;/&lt;FONT color="#800080"&gt;* &amp;lt;- Probably Need to change this */&lt;/FONT&gt;&lt;/STRONG&gt;
     %let High_Value = %scan(&amp;amp;High_DT_List, &amp;amp;t, ';'); &lt;STRONG&gt;/* &lt;FONT color="#800080"&gt;&amp;lt;- Probably Need to change this */&lt;/FONT&gt;&lt;/STRONG&gt;

    proc sql;
	     INSERT into FINAL_TABLE
         SELECT &amp;amp;Check_Number_Value., MEMBERID, DOB 
         From HAVE
		 Where DOB between &amp;amp;LowValue. and &amp;amp;High_Value.  &lt;FONT color="#FF0000"&gt; &lt;STRONG&gt;/* &amp;lt;- DEFINITLY Need to change this! */&lt;/STRONG&gt;&lt;/FONT&gt;

	 ;quit;
  
	 %end;


%mend FindRanges;

%FindRanges();&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;&amp;nbsp;What i'm hoping to have in the FINAL_TABLE would be:&lt;/P&gt;&lt;PRE&gt;&lt;CODE class=""&gt;FINAL_TABLE
&lt;U&gt;Check_Number&lt;/U&gt; &lt;U&gt;MEMBERID&lt;/U&gt;  &lt;U&gt;DOB&lt;/U&gt;
1     	     1111 	1/12/2001
2	     2222       2/11/2003
2	     3333       3/11/2003&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;Thanks so much!&lt;/P&gt;</description>
      <pubDate>Wed, 06 Nov 2024 14:16:23 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Multiple-Date-formats-in-a-single-Text-string/m-p/950031#M371549</guid>
      <dc:creator>Rebecca_K</dc:creator>
      <dc:date>2024-11-06T14:16:23Z</dc:date>
    </item>
    <item>
      <title>Re: Multiple Date formats in a single Text string</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Multiple-Date-formats-in-a-single-Text-string/m-p/950033#M371550</link>
      <description>&lt;P&gt;If you have hard coded macro variables that you want to work with, they cannot be in the CARDS part of a data step. Nevertheless, you can work with them in other ways. So range_check will have one observation, and you want to read the dates with Informat&amp;nbsp;MMDDYY10.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt; %let Hardcode_Low_DT = %sysevalf('02JAN2002'd);
 %let Hardcode_High_DT = %sysevalf('02DEC2003'd);&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;This turns the 02JAN2002 and 02DEC2003 into actual date values which SAS can work with. Your first SQL is unnecessary. You can turn the first row of RANGE_CHECK into macro variables with CALL SYMPUTX&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data _null_;
    set range_check(obs=1);
    call symputx('low_dt',low_dt);
    call symputx('high_dt',high_dt);
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;then in your second SQL you can do something like this&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;Where DOB between &amp;amp;low_dt and &amp;amp;high_dt&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;and/or&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;where dob between &amp;amp;Hardcode_Low_DT and &amp;amp;hardcode_high_dt&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 06 Nov 2024 15:00:00 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Multiple-Date-formats-in-a-single-Text-string/m-p/950033#M371550</guid>
      <dc:creator>PaigeMiller</dc:creator>
      <dc:date>2024-11-06T15:00:00Z</dc:date>
    </item>
    <item>
      <title>Re: Multiple Date formats in a single Text string</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Multiple-Date-formats-in-a-single-Text-string/m-p/950039#M371554</link>
      <description>&lt;P&gt;I would back up and think about non-macro approaches to implementing this sort of range check.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The idea of having a dataset range checks is a good one.&amp;nbsp; When you have date values in a dataset, you want to store them is date values (numeric variables), not character.&amp;nbsp; So your data could be like:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;DATA HAVE;
INPUT MEMBERID : $20. DOB : MMDDYY10.;
Format DOB MMDDYY10.;
CARDS;
1111 1/12/2001
2222 2/11/2003
3333 3/11/2003
4444 1/13/2000
;run;

DATA RANGE_CHECK;
INPUT Check_Number Low_DT : mmddyy10. High_DT : mmddyy10.;
format Low_DT High_Dt mmddyy10. ;
CARDS;
1 3/1/2000 5/1/2001
2 1/2/2002 12/2/2003
;run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&lt;BR /&gt;Note I removed the macro variables from the CARDS data.&amp;nbsp; That won't work. If you want to make this data dynamic, happy to discuss alternative approaches.&amp;nbsp; I also make Low_DT and High_DT numeric date variables, rather than character.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Once you have that data, there are lots of different way to implement the range check.&amp;nbsp; One would be to use PROC SQL.&amp;nbsp; Below will join every record in your data against every check, and output the records where DOB is in the range.&amp;nbsp; You'll get a note in your log that SAS is performing a Cartesian product.&amp;nbsp; In this case, four records from HAVE * 2 records in RANGE_CHECK would result in 8 records, which are then filtered.&amp;nbsp; If you have big data, the Cartesian product may be slow, but it's one way you could approach the problem.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc sql ;
  create table want as
  select b.check_number,a.memberid,a.dob
  from have as a
      ,range_check as b
  where b.low_dt&amp;lt;=a.dob&amp;lt;=b.high_dt
  ;
quit ;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you look on lexjansen.com (an archive of SAS papers written by users) and search for "range check", you'll find lots of different approaches to implementing checks like this.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 06 Nov 2024 15:34:55 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Multiple-Date-formats-in-a-single-Text-string/m-p/950039#M371554</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2024-11-06T15:34:55Z</dc:date>
    </item>
    <item>
      <title>Re: Multiple Date formats in a single Text string</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Multiple-Date-formats-in-a-single-Text-string/m-p/950040#M371555</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/19879"&gt;@Quentin&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;
&lt;P&gt;I would back up and think about non-macro approaches to implementing this sort of range check.&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Yes, excellent point by&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/19879"&gt;@Quentin&lt;/a&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 06 Nov 2024 15:39:44 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Multiple-Date-formats-in-a-single-Text-string/m-p/950040#M371555</guid>
      <dc:creator>PaigeMiller</dc:creator>
      <dc:date>2024-11-06T15:39:44Z</dc:date>
    </item>
  </channel>
</rss>

