<?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: Reading off reference table dynamically in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Reading-off-reference-table-dynamically/m-p/52194#M11001</link>
    <description>Essentially you are looking up the most recent loan rate.  The DATA step below creates a UNION of the two data sets using a SET statement.  Since the dates do not necessarily align we need to retain the loan rate.&lt;BR /&gt;
[pre]&lt;BR /&gt;
data rates;&lt;BR /&gt;
input Date yymmdd8. Rate;&lt;BR /&gt;
format date yymmdd10.;&lt;BR /&gt;
datalines;&lt;BR /&gt;
20100701 2.50&lt;BR /&gt;
20090801 2.25&lt;BR /&gt;
20090302 2.00&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
data loans;&lt;BR /&gt;
input CustomerID $ Date yymmdd8.;&lt;BR /&gt;
datalines;&lt;BR /&gt;
1 20090626&lt;BR /&gt;
2 20100708&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
proc sort data=rates;&lt;BR /&gt;
   by date;&lt;BR /&gt;
   run;&lt;BR /&gt;
&lt;BR /&gt;
data loanrate(keep=date loanrate customerid);&lt;BR /&gt;
    set rates(in=inrates)&lt;BR /&gt;
        loans(in=inloan);&lt;BR /&gt;
    by date;&lt;BR /&gt;
    retain loanrate;&lt;BR /&gt;
    if inrates then loanrate=rate;&lt;BR /&gt;
    if inloan;&lt;BR /&gt;
    run;&lt;BR /&gt;
[/pre]&lt;BR /&gt;
For this solution (which requires a BY statement), you may need to do more or less sorting depending on how your incoming data sets are ordered.</description>
    <pubDate>Mon, 19 Jul 2010 03:52:36 GMT</pubDate>
    <dc:creator>ArtC</dc:creator>
    <dc:date>2010-07-19T03:52:36Z</dc:date>
    <item>
      <title>Reading off reference table dynamically</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Reading-off-reference-table-dynamically/m-p/52193#M11000</link>
      <description>HI I have two tables. wonder if someone can assist me doing  the following:&lt;BR /&gt;
&lt;BR /&gt;
Table #1&lt;BR /&gt;
Date Rate&lt;BR /&gt;
20100701 2.50&lt;BR /&gt;
20090801 2.25&lt;BR /&gt;
20090302 2.00&lt;BR /&gt;
&lt;BR /&gt;
Table #2 (has 10,000 records)&lt;BR /&gt;
CustomerID Lending_Date&lt;BR /&gt;
1 20090626&lt;BR /&gt;
2 20100708&lt;BR /&gt;
&lt;BR /&gt;
Basically what i want to do is use the DB2 Table #1 as reference table  to add new column "rate" to customer Table #2. For example&lt;BR /&gt;
CustomerID #1 will get rate 2.00 because the lending_date is greater than 20090302 but less than 20090801&lt;BR /&gt;
&lt;BR /&gt;
Resulting table:&lt;BR /&gt;
CustomerID Lending_Date Rate&lt;BR /&gt;
1 20100626 2.00&lt;BR /&gt;
2 20100708 2.50&lt;BR /&gt;
 &lt;BR /&gt;
My challenge is that table #1 is a DB2 table that could be growing irregularly  and I will not be the one update the table. How can i get it done using data step?&lt;BR /&gt;
Thx</description>
      <pubDate>Mon, 19 Jul 2010 01:52:03 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Reading-off-reference-table-dynamically/m-p/52193#M11000</guid>
      <dc:creator>deleted_user</dc:creator>
      <dc:date>2010-07-19T01:52:03Z</dc:date>
    </item>
    <item>
      <title>Re: Reading off reference table dynamically</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Reading-off-reference-table-dynamically/m-p/52194#M11001</link>
      <description>Essentially you are looking up the most recent loan rate.  The DATA step below creates a UNION of the two data sets using a SET statement.  Since the dates do not necessarily align we need to retain the loan rate.&lt;BR /&gt;
[pre]&lt;BR /&gt;
data rates;&lt;BR /&gt;
input Date yymmdd8. Rate;&lt;BR /&gt;
format date yymmdd10.;&lt;BR /&gt;
datalines;&lt;BR /&gt;
20100701 2.50&lt;BR /&gt;
20090801 2.25&lt;BR /&gt;
20090302 2.00&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
data loans;&lt;BR /&gt;
input CustomerID $ Date yymmdd8.;&lt;BR /&gt;
datalines;&lt;BR /&gt;
1 20090626&lt;BR /&gt;
2 20100708&lt;BR /&gt;
run;&lt;BR /&gt;
&lt;BR /&gt;
proc sort data=rates;&lt;BR /&gt;
   by date;&lt;BR /&gt;
   run;&lt;BR /&gt;
&lt;BR /&gt;
data loanrate(keep=date loanrate customerid);&lt;BR /&gt;
    set rates(in=inrates)&lt;BR /&gt;
        loans(in=inloan);&lt;BR /&gt;
    by date;&lt;BR /&gt;
    retain loanrate;&lt;BR /&gt;
    if inrates then loanrate=rate;&lt;BR /&gt;
    if inloan;&lt;BR /&gt;
    run;&lt;BR /&gt;
[/pre]&lt;BR /&gt;
For this solution (which requires a BY statement), you may need to do more or less sorting depending on how your incoming data sets are ordered.</description>
      <pubDate>Mon, 19 Jul 2010 03:52:36 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Reading-off-reference-table-dynamically/m-p/52194#M11001</guid>
      <dc:creator>ArtC</dc:creator>
      <dc:date>2010-07-19T03:52:36Z</dc:date>
    </item>
    <item>
      <title>Re: Reading off reference table dynamically</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Reading-off-reference-table-dynamically/m-p/52195#M11002</link>
      <description>If this process runs in SAS, I would apply the rate through a format look-up. That allows the data to be in an order more relevant to the processing.&lt;BR /&gt;
Create the lookup format with : [pre]data cntlin ;&lt;BR /&gt;
   retain fmtname 'latest' start end label . hlo 'O' &lt;BR /&gt;
            sexcl 'N' eexcl 'Y' ; &lt;BR /&gt;
 * the "next date" is needed to define the rate date range but must be &lt;BR /&gt;
   excluded from the date range - so EEXCL =Y excludes end-of-range;&lt;BR /&gt;
   output ; * missing becomes missing ;&lt;BR /&gt;
   hlo = 'L' ;&lt;BR /&gt;
   label = .N ; * no rate prior to first date ;&lt;BR /&gt;
   * now output each rate for range up to following date ;&lt;BR /&gt;
   do while( not eof ) ;&lt;BR /&gt;
      set DB2.TABLE_1( rename=( date= end rate= label2 ))  end= eof ;&lt;BR /&gt;
    * &lt;B&gt;ensure&lt;/B&gt; db2_TABLE_1 is extracted &lt;B&gt;as a single row for each date and in date order&lt;/B&gt;;&lt;BR /&gt;
      output ;&lt;BR /&gt;
      hlo = ' ' ;&lt;BR /&gt;
       * next start follows after this end ;&lt;BR /&gt;
      start = end ;  &lt;BR /&gt;
      * the rate before the next date is the rate on this date ;&lt;BR /&gt;
      * so output this rate when next date becomes available ;&lt;BR /&gt;
      label = label2 ; &lt;BR /&gt;
   end ;&lt;BR /&gt;
   * now output final range which continues with no "end date" (hlo =H) ;&lt;BR /&gt;
   end = . ;&lt;BR /&gt;
   hlo= 'H' ;&lt;BR /&gt;
   output ;&lt;BR /&gt;
   stop ;&lt;BR /&gt;
run ;&lt;BR /&gt;
* now compile the format ;&lt;BR /&gt;
proc format cntlin= cntlin ; &lt;BR /&gt;
run ; * [/pre]  now use that date-lookup in this kind of way ;[pre]data whatever_update ;&lt;BR /&gt;
   set table_2 ;&lt;BR /&gt;
   rate = input( put( lending_date, latest. ), best10. ) ;&lt;BR /&gt;
run ;[/pre]&lt;BR /&gt;
Of course, it might be better to use the newer technology available since SAS9 introduced &lt;I&gt;associative arrays&lt;/I&gt; - otherwise knows as hash tables. In fact this would make a good example to be incorporated in the on-line doc</description>
      <pubDate>Mon, 19 Jul 2010 12:30:36 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Reading-off-reference-table-dynamically/m-p/52195#M11002</guid>
      <dc:creator>Peter_C</dc:creator>
      <dc:date>2010-07-19T12:30:36Z</dc:date>
    </item>
    <item>
      <title>Re: Reading off reference table dynamically</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Reading-off-reference-table-dynamically/m-p/52196#M11003</link>
      <description>...&lt;BR /&gt;
&amp;gt; Of course, it might be better to use the newer&lt;BR /&gt;
&amp;gt; technology available since SAS9 introduced&lt;BR /&gt;
&amp;gt; &lt;I&gt;associative arrays&lt;/I&gt; - otherwise knows as hash&lt;BR /&gt;
&amp;gt; tables. In fact this would make a good example to be&lt;BR /&gt;
&amp;gt; incorporated in the on-line doc&lt;BR /&gt;
...&lt;BR /&gt;
I don't think hash helps since the difficulty here is to lookup a date in a table with only the starting dates of  new rates. Your format approach works great because we can make a format with input *ranges*. &lt;BR /&gt;
&lt;BR /&gt;
If we first "expand" the rate table so that the rate is given for each day (from the earliest date to today), then things become really simple. We can put this "expanded" rates table into hash and do lookups, but a simple merge will do nicely as well.&lt;BR /&gt;
&lt;BR /&gt;
[pre]&lt;BR /&gt;
   /* test data */&lt;BR /&gt;
   data rates;&lt;BR /&gt;
     input date yymmdd8. rate;&lt;BR /&gt;
   cards;&lt;BR /&gt;
   20100701 2.50&lt;BR /&gt;
   20090801 2.25&lt;BR /&gt;
   20090302 2.00&lt;BR /&gt;
   ;&lt;BR /&gt;
   run;&lt;BR /&gt;
   data loans;&lt;BR /&gt;
     input id date yymmdd8.;&lt;BR /&gt;
   cards;&lt;BR /&gt;
   1 20090626&lt;BR /&gt;
   2 20100708&lt;BR /&gt;
   ;&lt;BR /&gt;
   run;&lt;BR /&gt;
&lt;BR /&gt;
   /* prep datasets. you don^t have to sort loans if you use hash to look up */&lt;BR /&gt;
   proc sort data=rates nodupkey;&lt;BR /&gt;
     by date;&lt;BR /&gt;
   run;&lt;BR /&gt;
   proc sort data=loans;&lt;BR /&gt;
     by date;&lt;BR /&gt;
   run;&lt;BR /&gt;
&lt;BR /&gt;
   /* expand rates table so that we can cover everyday&lt;BR /&gt;
      from min(date) to today. a single rate per day only. */&lt;BR /&gt;
   data daily;&lt;BR /&gt;
     format date yymmdd10.;&lt;BR /&gt;
     merge rates(rename=(date=start))&lt;BR /&gt;
           rates(firstobs=2 keep=date rename=(date=nextStart));&lt;BR /&gt;
     /* by omitted intentionally */&lt;BR /&gt;
     finish = ifn(missing(nextStart), today(), nextStart-1);&lt;BR /&gt;
     do date = start to finish;&lt;BR /&gt;
       output;&lt;BR /&gt;
     end;&lt;BR /&gt;
     keep date rate;&lt;BR /&gt;
   run;&lt;BR /&gt;
   /* attach rates to loans. simple merge. */&lt;BR /&gt;
   data loansr;&lt;BR /&gt;
     merge loans(in=inLoans) daily;&lt;BR /&gt;
     by date;&lt;BR /&gt;
     if inLoans;&lt;BR /&gt;
   run;&lt;BR /&gt;
&lt;BR /&gt;
   /* check */&lt;BR /&gt;
   proc print data=loansr noobs;&lt;BR /&gt;
   run;&lt;BR /&gt;
   /* on lst&lt;BR /&gt;
   id          date    rate&lt;BR /&gt;
    1    2009-06-26     2.0&lt;BR /&gt;
    2    2010-07-08     2.5&lt;BR /&gt;
   */&lt;BR /&gt;
[/pre]&lt;BR /&gt;
&lt;BR /&gt;
If you have an SAS/ETS licensed, then you can take advantage of PROC EXPAND to create the dataset daily (you have to append today's date first, then use BEGINNING and METHOD=STEP options in your CONVERT statement.)&lt;BR /&gt;
&lt;BR /&gt;
For the look-ups, simple merge is fine as above. If you insist using hash, then here you go:&lt;BR /&gt;
[pre]&lt;BR /&gt;
   data hash;&lt;BR /&gt;
     if 0 then set daily; /* to prep pdv */&lt;BR /&gt;
     if _n_=1 then do;&lt;BR /&gt;
       dcl hash h(dataset:'dailyRates');&lt;BR /&gt;
       h.defineKey('date');&lt;BR /&gt;
       h.defineData('rate');&lt;BR /&gt;
       h.defineDone();&lt;BR /&gt;
     end;&lt;BR /&gt;
     set loans;&lt;BR /&gt;
     h.find();&lt;BR /&gt;
   run;&lt;BR /&gt;
&lt;BR /&gt;
   /* check */&lt;BR /&gt;
   proc compare base=loansr compare=hash;&lt;BR /&gt;
   run;&lt;BR /&gt;
   /* on lst -- in part&lt;BR /&gt;
   NOTE: No unequal values were found. All values compared are exactly equal.&lt;BR /&gt;
   */&lt;BR /&gt;
[/pre]</description>
      <pubDate>Thu, 23 Sep 2010 22:24:16 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Reading-off-reference-table-dynamically/m-p/52196#M11003</guid>
      <dc:creator>chang_y_chung_hotmail_com</dc:creator>
      <dc:date>2010-09-23T22:24:16Z</dc:date>
    </item>
  </channel>
</rss>

