One of the things that I had to do recently was develop an example iReport which would exemplify how to achieve optional variables solely through the Java code within the JRXML file. My example consisted of creating a query that could serve as an example table named people which contained the following columns:

  • id
  • first_name
  • last_name
  • title
  • birth_date
  • is_deleted

The Lesser Solution

Of course, since a person’s birth date is normally considered slightly more confidential than their age, I decided to calculate the user’s age in years. At first, I didn’t think there was a built-in way to do this in PostgreSQL so I decided to write an arithmetic query. Since my sample iReport should be able to run on any PostgreSQL database, I decided against writing a custom function. Instead, I did something similar to the following:

SELECT id,
  first_name,
  last_name,
  title,
  DATE_PART('year', NOW()) - DATE_PART('year', birth_date)
  - CASE TO_CHAR(NOW(), 'MMDD') < TO_CHAR(birth_date, 'MMDD')
      WHEN TRUE THEN 1
      ELSE 0
    END AS age
FROM people
WHERE is_deleted = FALSE

Assuming the people table actually contains records where is_deleted is FALSE, the above query will return those records with the ages of the people instead of their birth dates. First, I subtracted the birth_date year from the current year. Next I format both the current date and the birth_date in the MMDD format. If when comparing the resulting strings, the MMDD string for the current date precedes that format for the birth_date, this means that the additional full year calculated before needs to be removed, otherwise the current calculation will stay. For example, if today’s date is September 19, 2011 and the birth date is September 23, 1984, the first part would be 2011 – 1984 which equals 27. The second part would see if “0919” comes before “0923”. Since “0919” does come before “0923”, 1 is subtracted from the 27 to give us a total of 26 years.

The Best Solution

As I stated when I first wrote this post, I am definitely not a PostgreSQL wizard, in fact I am definitely more of a JavaScript guy than anything. Therefore @Frank helped me out by proposing a better solution which used the AGE function which produces an INTERVAL and then used the EXTRACT function to pull the year from the INTERVAL. Therefore, after using his proposed answer (which I successfully tested), the query looks like the following:

SELECT id,
  first_name,
  last_name,
  title,
  EXTRACT(year FROM age(birth_date)) AS age
FROM people
WHERE is_deleted = FALSE
Categories: BlogSQL

3 Comments

Frank · September 20, 2011 at 2:17 AM

Use the SQL-function AGE() to calculate an age, much easier.

Frank · September 20, 2011 at 3:28 AM

SELECT EXTRACT(year FROM age('September 23, 1984'::date));

cwest · September 20, 2011 at 9:44 AM

@Frank thank you very much for this. I am going to update my post with your better solution and will give you credit.

Leave a Reply

Your email address will not be published. Required fields are marked *