<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Matt Oldham</title>
	<atom:link href="http://www.mattoldham.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mattoldham.com</link>
	<description></description>
	<lastBuildDate>Mon, 16 Apr 2012 12:24:09 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Calculating Age Based on Date of Birth in SQLite</title>
		<link>http://www.mattoldham.com/2011/05/calculating-age-based-on-date-of-birth-in-sqlite/</link>
		<comments>http://www.mattoldham.com/2011/05/calculating-age-based-on-date-of-birth-in-sqlite/#comments</comments>
		<pubDate>Tue, 31 May 2011 16:07:20 +0000</pubDate>
		<dc:creator>-Matt-</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>

		<guid isPermaLink="false">http://www.mattoldham.com/?p=170</guid>
		<description><![CDATA[On a recent project I needed to calculate a person&#8217;s age relative to the system date based on an input value of a birth date.  In this particular scenario I needed to do so using the SQLite engine, and the specific requirement was to calculate age using the following logic: If person is younger than <a href='http://www.mattoldham.com/2011/05/calculating-age-based-on-date-of-birth-in-sqlite/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">On a recent project I needed to calculate a person&#8217;s age relative to the system date based on an input value of a birth date.  In this particular scenario I needed to do so using the SQLite engine, and the specific requirement was to calculate age using the following logic:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">If person is younger than 1 month, present the age in days (e.g. 30 days)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">If person is 1 month or older but younger than 2 months, present the age in weeks (e.g. 8 wks)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">If person is 2 months or older but younger than one year, present the age in months (e.g. 3 mos)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">If person is 1 year or older, present the age in years (e.g. 2 yrs)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">My initial thought was obviously &lt;i&gt;not&lt;/i&gt; to reinvent the wheel, so I did what any logical database guy would do &#8211; I consulted the SQLite documentation for what I expected to be a plethora of date-specific SQL functions I could leverage.  After all, other RDBMS implementations offer direct support for the functionality I needed.  PostgreSQL, for example offers the age function (http://www.postgresql.org/docs/9.0/static/functions-datetime.html).</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">If you are familiar at all with SQLite you have probably been faced with the interesting implementation of dynamic data types.  One example of this is the fact that there is no native &#8220;date&#8221; data type.  One nuance that stems from this implementation is the seemingly limited set of options when it comes to date functions &#8211; at least upon initial observation.</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">I found a number of posts (like this one http://stackoverflow.com/questions/3123951/sqlite-how-to-calculate-age-from-birth-date) that discussed calculating such date values using the built-in SQLite functions, however they fell short in getting to the granularity I needed.  Other posts (such as this one http://www.mail-archive.com/sqlite-users@sqlite.org/msg20531.html) suggested writing my own custom SQLite function in C.  This was not an option since my particular requirement relied on using the SQLite implementation inside the context of the Adobe Flash player.  So, I was ultimately left to fend for myself, and this kind of challenge is what developers sometimes need to stoke their initiative and get their creative wheels turning.  It definitely worked for me, not that I needed the motivation <img src='http://www.mattoldham.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Before I started, I knew that I would need a decent set of data against which to test my SQL.  As I typically tend to do for such needs, I fired up Microsoft Excel and generated a list of dates along with their corresponding years/months/days calculations using basic Excel functions.  I then turned the resulting Excel data into SQL INSERT statements and loaded them into a SQLite table named AGE_TEST for testing.  Here&#8217;s an excerpt of the Excel data, based on my local system date of 5/31/2011:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
<pre class="brush: plain; title: ; notranslate">&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;DOB      Years  Months  Days&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;9/11/05      5       8    20&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;1/1/10       1       4    30&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;1/2/10       1       4    29&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;...&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;5/29/11      0       0     2&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;5/30/11      0       0     1&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;5/31/11      0       0     0&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">And here are the respective Excel formulae I used:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
<pre class="brush: plain; title: ; notranslate">&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;Years:  =DATEDIF(A2,TODAY(),&quot;Y&quot;)&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;Months: =DATEDIF(A7,TODAY(),&quot;YM&quot;)&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;Days:   =DATEDIF(A7,TODAY(),&quot;MD&quot;)&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;</pre>
</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">After a bit of trial and error, I finally ended up with something that worked across all of my test dates.  Admittedly (as you can probably tell from the code), the months calculation was the most challenging.  Here&#8217;s the SQL solution I ended up with:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">
<pre class="brush: sql; title: ; notranslate">&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;SELECT CASE&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;/* DOB is beyond current date */&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN dob &gt; date('now') THEN NULL&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;/* DOB equal to current date */&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN dob = date('now') THEN '0 days'&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;/* subject is less that 1 month old */&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-1 month') &lt; dob THEN CAST((julianday('now') - julianday(dob)) AS INTEGER) || ' days'&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;/* subject is less that 2 months old */&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-2 month') &lt; dob THEN CAST((julianday('now') - julianday(dob))/7 AS INTEGER) || ' wks'&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;/* subject is less than 1 year old */&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-1 year') &lt; dob THEN&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;CASE&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-11 month') &gt;= dob then 11&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-10 month') &gt;= dob then 10&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-9 month') &gt;= dob then 9&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-8 month') &gt;= dob then 8&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-7 month') &gt;= dob then 7&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-6 month') &gt;= dob then 6&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-5 month') &gt;= dob then 5&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-4 month') &gt;= dob then 4&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-3 month') &gt;= dob then 3&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-2 month') &gt;= dob then 2&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN date('now','-1 month') &gt;= dob then 1&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;END || ' mos'&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;/* subject is 1 year or older */&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;ELSE ((strftime('%Y', 'now') - strftime('%Y', dob)) -&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;(CASE&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;WHEN (strftime('%m', dob) &lt; strftime('%m', 'now')) OR&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;(strftime('%m', dob) = strftime('%m', 'now') AND&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;strftime('%d', dob) &lt;= strftime('%d', 'now')) THEN 0&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;ELSE 1&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;END)) || ' yrs'&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;END AS person_age&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;FROM (SELECT dob&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;FROM age_test)&lt;/div&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;&quot;&gt;</pre>
</div>
<div>On a recent project I needed to calculate a person&#8217;s age relative to the system date based on an input value of a birth date.  In this particular scenario I needed to do so using the SQLite engine, and the specific requirement was to calculate age using the following logic:</div>
<div>
<ul>
<li>If person is younger than 1 month, present the age in days (e.g. 30 days)</li>
<li>If person is 1 month or older but younger than 2 months, present the age in weeks (e.g. 8 wks)</li>
<li>If person is 2 months or older but younger than one year, present the age in months (e.g. 3 mos)</li>
<li>If person is 1 year or older, present the age in years (e.g. 2 yrs)</li>
</ul>
</div>
<p><span id="more-170"></span>My initial thought was obviously to <em>not</em> reinvent the wheel, so I did what any logical database guy would do &#8211; I consulted the <a href="http://www.sqlite.org/datatype3.html" target="_blank">SQLite documentation</a> for what I expected to be a plethora of date-specific SQL functions I could leverage.  After all, other RDBMS implementations offer direct support for the functionality I needed.  PostgreSQL, for example offers the <a href="http://www.postgresql.org/docs/9.0/static/functions-datetime.html" target="_blank">age</a> function.</p>
<div>If you are familiar at all with SQLite you have probably been faced with the interesting implementation of dynamic data types.  One example of this is the fact that there is no native &#8220;date&#8221; data type.  One nuance that stems from this implementation is the seemingly limited set of options when it comes to date functions &#8211; at least upon initial observation.</div>
<p>I found a number of posts (like <a href="http://stackoverflow.com/questions/3123951/sqlite-how-to-calculate-age-from-birth-date" target="_blank">this</a> one) that discussed calculating such date values using the built-in SQLite functions, however they fell short in getting to the granularity I needed.  Other posts (such as <a href="http://www.mail-archive.com/sqlite-users@sqlite.org/msg20531.html" target="_blank">this</a> one) suggested writing my own custom SQLite function in C.  This was not an option since my particular requirement relied on using the SQLite implementation inside the context of the Adobe Flash player.  So, I was ultimately left to fend for myself, and this kind of challenge is what developers sometimes need to stoke their initiative and get their creative wheels turning.  It definitely worked for me, not that I needed the motivation <img src='http://www.mattoldham.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Before I started, I knew that I would need a decent set of data against which to test my SQL.  As I typically tend to do for such needs, I fired up Microsoft Excel and generated a list of dates along with their corresponding years/months/days calculations using basic Excel functions.  I then turned the resulting Excel data into SQL INSERT statements and loaded them into a SQLite table named AGE_TEST for testing.  Here&#8217;s an excerpt of the Excel data, based on my local system date of 5/31/2011:</p>
<div>
<pre class="brush: plain; title: ; notranslate">
DOB      Years  Months  Days
9/11/05      5       8    20
1/1/10       1       4    30
1/2/10       1       4    29
...
5/29/11      0       0     2
5/30/11      0       0     1
5/31/11      0       0     0
</pre>
</div>
<div>And here are the respective Excel formulae I used:</div>
<div>
<pre class="brush: plain; title: ; notranslate">
Years:  =DATEDIF(A2,TODAY(),&quot;Y&quot;)
Months: =DATEDIF(A2,TODAY(),&quot;YM&quot;)
Days:   =DATEDIF(A2,TODAY(),&quot;MD&quot;)
</pre>
</div>
<div>After a bit of trial and error, I finally ended up with something that worked across all of my test dates.  Admittedly (as you can probably tell from the code), the months calculation was the most challenging.  Here&#8217;s the SQL solution I ended up with:</div>
<div>
<pre class="brush: sql; title: ; notranslate">
SELECT CASE
          /* DOB is beyond current date */
          WHEN dob &gt; date('now') THEN NULL
          /* DOB equal to current date */
          WHEN dob = date('now') THEN '0 days'
          /* subject is less that 1 month old */
          WHEN date('now','-1 month') &lt; dob THEN CAST((julianday('now') - julianday(dob)) AS INTEGER) || ' days'
          /* subject is less that 2 months old */
          WHEN date('now','-2 month') &lt; dob THEN CAST((julianday('now') - julianday(dob))/7 AS INTEGER) || ' wks'
          /* subject is less than 1 year old */
          WHEN date('now','-1 year') &lt; dob THEN
             CASE
                WHEN date('now','-11 month') &gt;= dob then 11
                WHEN date('now','-10 month') &gt;= dob then 10
                WHEN date('now','-9 month') &gt;= dob then 9
                WHEN date('now','-8 month') &gt;= dob then 8
                WHEN date('now','-7 month') &gt;= dob then 7
                WHEN date('now','-6 month') &gt;= dob then 6
                WHEN date('now','-5 month') &gt;= dob then 5
                WHEN date('now','-4 month') &gt;= dob then 4
                WHEN date('now','-3 month') &gt;= dob then 3
                WHEN date('now','-2 month') &gt;= dob then 2
                WHEN date('now','-1 month') &gt;= dob then 1
             END || ' mos'
          /* subject is 1 year or older */
          ELSE ((strftime('%Y', 'now') - strftime('%Y', dob)) -
                (CASE
                    WHEN (strftime('%m', dob) &lt; strftime('%m', 'now')) OR
                         (strftime('%m', dob) = strftime('%m', 'now') AND
                          strftime('%d', dob) &lt;= strftime('%d', 'now')) THEN 0
                    ELSE 1
                 END)) || ' yrs'
          END AS person_age
  FROM (SELECT dob
          FROM age_test)
</pre>
<p>I&#8217;d love to hear your thoughts.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.mattoldham.com/2011/05/calculating-age-based-on-date-of-birth-in-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Make a Long Running Query</title>
		<link>http://www.mattoldham.com/2010/08/how-to-make-a-long-running-query/</link>
		<comments>http://www.mattoldham.com/2010/08/how-to-make-a-long-running-query/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 14:06:30 +0000</pubDate>
		<dc:creator>-Matt-</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://www.mattoldham.com/?p=142</guid>
		<description><![CDATA[Recently a colleague sent me a quick instant message asking if I knew of any way in Oracle to make a query run long enough to test a &#8220;cancel query&#8221; function he was writing in Java.  He had tried several queries that usually produced the results he was looking for, however there wasn&#8217;t enough data <a href='http://www.mattoldham.com/2010/08/how-to-make-a-long-running-query/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p>Recently a colleague sent me a quick instant message asking if I knew of any way in Oracle to make a query run long enough to test a &#8220;cancel query&#8221; function he was writing in Java.  He had tried several queries that usually produced the results he was looking for, however there wasn&#8217;t enough data in his test environment to reproduce the wait time he needed.  I thought about it for a minute and then proposed the following solution.</p>
<p>Oracle provides the <a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10577/d_lock.htm#sthref5204" target="_blank">DBMS_LOCK</a> package which allows users to manage their own locks.  One handy subprogram in this package in the SLEEP method, which suspends the current session for the specified number of seconds.  I have used DBMS_LOCK.SLEEP a number of times in the past so I knew this would do the trick.<span id="more-142"></span></p>
<p>The first thing needed was the ability to execute this package method, which is not something granted to all users by default.  I had my colleague issue the following grant as the SYS user in his test database:</p>
<pre><pre class="brush: plain; title: ; notranslate">GRANT EXECUTE ON DBMS_LOCK TO public;</pre>
<p>Once that was done, all that was needed was a quick function to make his query run long.  Hence, the following:</p>
<pre><pre class="brush: plain; title: ; notranslate">CREATE OR REPLACE FUNCTION query_wait
(
   i_wait_secs IN PLS_INTEGER
)
   RETURN NUMBER
IS
BEGIN
   DBMS_LOCK.SLEEP(i_wait_secs);
   RETURN i_wait_secs;
END;
/</pre>
<p>Here&#8217;s our new helper function in action:</p>
<pre><pre class="brush: plain; title: ; notranslate">matt:~&amp;gt;sqlplus scott/tiger@local

SQL*Plus: Release 11.2.0.1.0 Production on Tue Aug 24 05:55:54 2010

Copyright (c) 1982, 2009, Oracle.  All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL&amp;gt; SET TIMING ON

SQL&amp;gt; SELECT query_wait(10)
  2    FROM dual
  3  /

QUERY_WAIT(10)
--------------
            10

Elapsed: 00:00:10.01</pre>
<p>And that&#8217;s all there is to it.  Instant, long running queries.  Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mattoldham.com/2010/08/how-to-make-a-long-running-query/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Handy Desktop Background For App Developers</title>
		<link>http://www.mattoldham.com/2010/02/handy-desktop-background-for-app-developers/</link>
		<comments>http://www.mattoldham.com/2010/02/handy-desktop-background-for-app-developers/#comments</comments>
		<pubDate>Tue, 02 Feb 2010 22:39:50 +0000</pubDate>
		<dc:creator>-Matt-</dc:creator>
				<category><![CDATA[Development]]></category>

		<guid isPermaLink="false">http://www.mattoldham.com/?p=122</guid>
		<description><![CDATA[Ever been working with an application window and wondered if it would fit into a particular screen resolution?  I have.  I am continually testing our apps in different browser windows and periodically I check to make sure we are still within the maximum screen resolution as indicated in our requirements documents.  I had been using <a href='http://www.mattoldham.com/2010/02/handy-desktop-background-for-app-developers/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p>Ever been working with an application window and wondered if it would fit into a particular screen resolution?  I have.  I am continually testing our apps in different browser windows and periodically I check to make sure we are still within the maximum screen resolution as indicated in our requirements documents.  I had been using this <a href="http://www.yellowpipe.com/yis/tools/window_resizer/" target="_blank">nifty little Firefox plugin</a> which did the job for me.  But, I don&#8217;t have that capability yet (that I know of) with Google Chrome.  And, what if I happen to be testing a non-browser-based application?  Well, I got tired of wondering and decided to do something about it.<span id="more-122"></span></p>
<p>I remember from a previous life having worked with a developer who had a very neat desktop background that demarcated the different resolutions with a label and border so that regardless of which application or window he was working in he could tell immediately how well it fit into a particular resolution simply by moving the window over the different sections of his desktop.  I did a bit of searching and turned up nothing in the way of desktop backgrounds that fit the bill, so I&#8217;m guessing maybe he did what I did &#8211; create my own.</p>
<p>Since I run a screen resolution of 1680&#215;1150 on <a href="http://www.mattoldham.com/2009/09/a-great-development-configuration/" target="_self">my HP laptop</a> I&#8217;ve started with, well, a 1680&#215;1150 image.  You can see that I like darks colors on my desktop, and the final version has a nice little gradient to spice it up a bit.  Conky overlays it very nicely, and I now have a great solution to my problem.</p>
<p style="text-align: left;">Here&#8217;s a screenshot of the final product running on my laptop:</p>
<p style="text-align: center;"><a href="http://www.mattoldham.com/wp-content/uploads/2010/02/my_screen.png"><img class="size-thumbnail wp-image-120 aligncenter" title="My Desktop" src="http://www.mattoldham.com/wp-content/uploads/2010/02/my_screen-150x150.png" alt="My Desktop" width="150" height="150" /></a></p>
<p style="text-align: left;">Here&#8217;s the Gimp .xcf file with all the layers for the 1680&#215;1150 resolution.  Those of you who run larger screen resolutions can take it and modify to fit your needs.</p>
<p style="text-align: left;"><a href="http://www.mattoldham.com/wp-content/uploads/2010/02/desktop_screen_res_bg_1650x1150.xcf">desktop_screen_res_bg_1650x1150.xcf</a></p>
<p style="text-align: left;">And, here is the .png file for those of you already running 1680&#215;1150.</p>
<p style="text-align: left;"><a href="http://www.mattoldham.com/wp-content/uploads/2010/02/desktop_screen_res_bg_1650x1150.png">desktop_screen_res_bg_1650x1150.png</a></p>
<p style="text-align: left;">Hope you enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mattoldham.com/2010/02/handy-desktop-background-for-app-developers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OLAP Friendly OLTP Design</title>
		<link>http://www.mattoldham.com/2009/11/olap-friendly-oltp-design/</link>
		<comments>http://www.mattoldham.com/2009/11/olap-friendly-oltp-design/#comments</comments>
		<pubDate>Wed, 11 Nov 2009 13:19:38 +0000</pubDate>
		<dc:creator>-Matt-</dc:creator>
				<category><![CDATA[Data Warehousing]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Business Intelligence]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://www.mattoldham.com/?p=92</guid>
		<description><![CDATA[I thought I would post a whitepaper I wrote earlier this year under the auspices of my employer, M. Miller &#38; Associates.  This whitepaper is basically a summary of things I have observed over the course of my career in IT, particularly in regard to database design.  I can assure you that I eat my <a href='http://www.mattoldham.com/2009/11/olap-friendly-oltp-design/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p>I thought I would post a whitepaper I wrote earlier this year under the auspices of my employer, <a href="http://www.mmillerassociates.com" target="_blank">M. Miller &amp; Associates</a>.  This whitepaper is basically a summary of things I have observed over the course of my career in IT, particularly in regard to database design.  I can assure you that I eat my own dog food when it comes to the things I discuss.  I&#8217;m in the trenches every day putting into practice these concepts in order to produce solid, forward thinking designs.  We&#8217;ll eventually post this on the company website, but until then I make it available here in hopes it provokes thought and discussion.  Let me know what you think.</p>
<p><a rel="attachment wp-att-96" href="http://www.mattoldham.com/2009/11/olap-friendly-oltp-design/olap-fiendly-oltp-design-planning-ahead-for-the-inevitable-data-warehouse/"></a><a href="http://www.mattoldham.com/wp-content/uploads/2009/11/OLAP-Fiendly-OLTP-Design-Planning-Ahead-for-the-Inevitable-Data-Warehouse.pdf">OLAP Fiendly OLTP Design &#8211; Planning Ahead for the Inevitable Data Warehouse</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mattoldham.com/2009/11/olap-friendly-oltp-design/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Great Development Configuration</title>
		<link>http://www.mattoldham.com/2009/09/a-great-development-configuration/</link>
		<comments>http://www.mattoldham.com/2009/09/a-great-development-configuration/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 18:32:31 +0000</pubDate>
		<dc:creator>-Matt-</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Apache Ant]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[openSuse]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Oyen]]></category>
		<category><![CDATA[Subversion]]></category>
		<category><![CDATA[UEX]]></category>
		<category><![CDATA[VMWare]]></category>

		<guid isPermaLink="false">http://www.mattoldham.com/?p=30</guid>
		<description><![CDATA[My current development environment has to be the best configuration I&#8217;ve had to date in my development career.  Here are some of the specifics: HP EliteBook laptop (8730w) 2.4GHz Core 2 Duo 64-bit 6GB Memory openSuse 11.1 64-bit The move to Linux from Windows has been a huge plus, though not without its own challenges.  <a href='http://www.mattoldham.com/2009/09/a-great-development-configuration/' class='excerpt-more'>[...]</a>]]></description>
				<content:encoded><![CDATA[<p>My current development environment has to be the best configuration I&#8217;ve had to date in my development career.  Here are some of the specifics:</p>
<ul>
<li>HP EliteBook laptop (8730w)</li>
<li> 2.4GHz Core 2 Duo 64-bit</li>
<li> 6GB Memory</li>
<li>openSuse 11.1 64-bit</li>
</ul>
<p>The move to Linux from Windows has been a huge plus, though not without its own challenges.  But it&#8217;s not just the hardware and OS.  Here are the tools that round out a highly productive development environment:<span id="more-30"></span></p>
<ul>
<li><a href="http://www.oracle.com/technology/products/database/xe/index.html" target="_blank">Oracle 10g Express Edition (XE)</a> Cost: $0.  I have been using Oracle since 1998 and can tell you that XE is a huge step forward in providing developers a full Oracle functionality with a small footprint.  And, it&#8217;s free.  We have each developer install a local copy from which we do our individual development database builds.  The database build process (which is performed using Apache Ant) required a bit of special XE configuration to work properly, but is by far one of the best features of our agile development and implementation process.  I am eagerly awaiting Oracle&#8217;s release of the 11g version of XE.</li>
<li><a href="http://www.oracle.com/technology/products/database/sql_developer/index.html" target="_blank">Oracle SQL Developer</a> Cost: $0.  Currently using version 1.5.5.  It&#8217;s not TOAD, which is what I grew up using, but it is slowly gaining all the features of TOAD and more.  All in all, I am satisfied.</li>
<li><a href="(http://www.oracle.com/technology/products/database/datamodeler/index.html" target="_blank">Oracle SQL Developer Data Modeler</a> Cost: $0.  All I can say is &#8220;Wow&#8221;!  I have been looking at data modeling tools for a long time.  My favorite was Oracle Designer back in the day, but I have primarily used ERwin in most of my work.  My frustration was that there was always something missing in terms of features and functionality.  Not so with this new (and, currently, free) tool from Oracle.  I immediately incorporated it into our development process and have not looked back.  If you are looking for a fully featured data modeling tool that will work for Oracle, SQL Server (2000 and 2005), and DB2 &#8211; this is the tool for you.</li>
<li><a href="http://ant.apache.org/" target="_blank">Apache Ant</a> Cost: $0.  When I was first introduced to Ant I was skeptical to say the least.  For a Java developer, sure&#8230; but for the database?  I mean, what could possibly be done with that basic &lt;sql&gt; task?  Boy was I missing out.  After a bit of reading and experimentation (and a ton of insight from a <a href="http://www.incursiontech.com" target="_blank">very smart friend</a> and colleague) I had a full blown agile database build utility on my hands.  I can&#8217;t say enough good things about Ant.</li>
<li><a href="http://subversion.tigris.org/" target="_blank">Subversion (SVN)</a> Cost: $0.  Nothing more to say here.  The breadth of the user community says it all.</li>
<li><a href="http://www.syntevo.com/smartsvn/index.html" target="_blank">SmartSVN</a> Cost $0.  For a Linux development environment, this is a great graphical client for SVN.  While it&#8217;s not needed since you can do all the work with SVN from the command line, it has a load of features even without enabling the Professional version.</li>
<li><a href="http://tortoisesvn.tigris.org/" target="_blank">TortoiseSVN</a> Cost: $0. For a Windows development environment, this is definitely the best SVN client.  Native Windows Explorer integration makes all the difference.  Developed by the same group who maintains Subversion, <a href="http://www.tigris.org/" target="_blank">Tigris</a>.  Now, if only they would port it to one of the Gnome/KDE file managers with the same level of integration.</li>
<li><a href="http://www.codeweavers.com/products/cxlinux/" target="_blank">Crossover Linux (Standard)</a> Cost: $40.  If you need to run windows applciations natively in Linux, this is probably the solution.  I&#8217;m not the biggest fan of it but it&#8217;s the best (if not only viable) alternative and it does do the job. Office 2007 is supported, BTW.</li>
<li>UltraEdit for Linux, aka <a href="http://www.ultraedit.com/products/uex.html" target="_blank">UEX</a> Ohhhh yeah, finally a VI alternative with all the bells and whistles you could ask for.  I have been using UE since 1997, and I can honestly say I use it every day.  UEX is still in beta, but that hasn&#8217;t stopped me from using it.  My hope is that I can transfer my UE license to UEX &#8211; we&#8217;ll see.</li>
<li><a href="http://www.vmware.com/products/ws/" target="_blank">VMWare Workstation</a> Cost: $189.  Yes there are other options here (like the free VirtualBox tool from Sun), but you cannot go wrong with VMWare.  Tried and true.</li>
</ul>
<p>Do you see the pattern?  Open source and free (or at least low cost).  Not necessarily the path of least resistance, but the best things are seldom the easiest to come by.</p>
<p>Also, if you happen to be looking for a good portable hard drive with high capacity and a low profile, take a look at <a href="http://oyendigital.com/" target="_blank">OyenDigital</a>.  I am currently using the <a href="http://oyendigital.com/esata-hard-drive.html" target="_blank">500GB External 2.5-inch eSATA/USB Portable Hard Drive</a> for which I paid $130.  While it&#8217;s only 5400RPM, I can still run virtual machines over the eSATA connection with no problems.  We have a second one (320GB model) we carry with us that contains our full SCM environment running in a Linux VM.  Plug it in, fire up the VM, and we are set.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mattoldham.com/2009/09/a-great-development-configuration/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Welcome!</title>
		<link>http://www.mattoldham.com/2009/09/welcome/</link>
		<comments>http://www.mattoldham.com/2009/09/welcome/#comments</comments>
		<pubDate>Tue, 08 Sep 2009 13:53:38 +0000</pubDate>
		<dc:creator>-Matt-</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.mattoldham.com/?p=5</guid>
		<description><![CDATA[Welcome to mattoldham.com.  This is something I have been considering for quite some time but have just never taken the time to get off the ground. Finally, today is the day.]]></description>
				<content:encoded><![CDATA[<p>Welcome to mattoldham.com.  This is something I have been considering for quite some time but have just never taken the time to get off the ground. Finally, today is the day. My intention is to post content on a variety of topics and hopefully of interest to many people.  I hope you find it helpful, thought-provoking, and encouraging.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mattoldham.com/2009/09/welcome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
