Tuesday, December 18, 2007

How to emulate the Oracle decode function/crosstab with boolean logic

How to emulate the Oracle decode function/crosstab with boolean logic
----------------------------------------------------------------------------------

From the Rozenshteins book, "Advanced SQL", there is the concept of characteristic functions: the delta function. For a Boolean expression such as A = B is written delta[A = B]. Its definition is that delta[A = B] = 1 whenever A = B is true and delta[A = B] = 0 otherwise. For delta[ au_ord = 1 ] , the translation is ( 1 - abs( sign( au_ord - 1 ) ) ).

If you want to test a field to see if it is equal to a value, say 100, use the following code:

SELECT ( 1 - ABS( SIGN( ISNULL( 100 - , 1 ) ) ) )

The innermost function will return 1 when the field is null, a positive value if the field <> 100 and will return 0 if the field = 100. This example is for Sybase or Microsoft SQL server, but other servers should support most of these functions or the COALESCE() function, which is the ANSI equivalent to ISNULL.


The SIGN() function returns zero for a zero value, -1 for a negative value, 1 for a positive value The ABS() function returns zero for a zero value, and > 1 for any non-zero value. In this case it will return 0 or 1 since the argument is the function SIGN(), thus acting as a binary switch.

Put it all together and you get '0' if the value match, and '1' if they don't. This is not that useful, so we subtract this return value from '1' to invert it, giving us a TRUE value of '1' and a false value of '0'. These return values can then be multiplied by the value of another column, or used within the parameters of another function like SUBSTRING() to return a conditional text value.

This is a neat way to use boolean logic to perform cross-tab or rotation queries easily, and very efficiently. Using the aggregate 'Group By' clause in a query and the ISNULL(), SIGN(), ABS(), SUBSTRING() and CHARINDEX() functions, you can create queries and views to perform all kinds of summarizations but this technique does not produce easily understood SQL statements.

No comments: