sexta-feira, 24 de outubro de 2014

Oracle DB Using the GREATEST function with null dates/values

The GREATEST function allows to compare values of different n columns.

According to Oracle documentation:

GREATEST returns the greatest of the list of one or more expressions. Oracle Database uses the first expr to determine the return type. If the first expr is numeric, then Oracle determines the argument with the highest numeric precedence, implicitly converts the remaining arguments to that datatype before the comparison, and returns that datatype. If the first expr is not numeric, then each expr after the first is implicitly converted to the datatype of the first exprbefore the comparison.
Oracle Database compares each expr using nonpadded comparison semantics. The comparison is binary by default and is linguistic if the NLS_COMP parameter is set to LINGUISTIC. Character comparison is based on the numerical codes of the characters in the database character set and is performed on whole strings treated as one sequence of bytes, rather than character by character. If the value returned by this function is character data, then its datatype is alwaysVARCHAR2.
 And this are some sample usages:

GREATEST(2, 5, 12, 3)
Result: 12

GREATEST('2', '5', '12', '3')
Result: '5'

GREATEST( 09/21/2013, 01/02/2012, 09/21/2013) -- columns typed as dates
Result: 09/21/2013

GREATEST('apples', 'applis', 'applas')
Result: 'applis'
The problem emerges when trying to a null value:

GREATEST( 09/21/2013, NULL, 09/21/2013) -- columns typed as dates
Result: NULL            

GREATEST('apples', 'applis', NULL)
Result: NULL            
To avoid this you can use the NVL() function that replaces a NULL value with a string. If you are handling dates then after that conversion you still need to convert it to_date(). This is the query that will work if you're business only requires dates bigger than 1900-01-01.


Col A         Col  B          GREATEST_DATE
---------------------------------------
 NULL          NULL            NULL
 09-21-2013    01-02-2012      09-21-2013
 NULL          01-03-2013      01-03-2013 
 01-03-2013    NULL            01-03-2013
Col A         Col  B          GREATEST_DATE
---------------------------------------
 NULL          NULL            1900-01-01
 09-11-2013    01-02-2012      09-11-2013
 NULL          01-03-2013      01-03-2013 
 01-03-2013    NULL            01-03-2013