This article shows you a possible solution to handle rounding issues in Teradata.

Let’s assume we have the following table definition:

CREATE VOLATILE TABLE ROUNDING_PROBLEM

(

AMOUNT DECIMAl(18,2),

MONTHS INTEGER

) NO PRIMARY INDEX ON COMMIT PRESERVE ROWS;

INSERT INTO ROUNDING_PROBLEM VALUES (10.25,3);

Let’s further assume that our task is to divide each amount by the number of months; this means per record you have to do the following calculation:

AMOUNT / MONTHS

This is not challenging from an implementation point of view but leads to Teradata rounding problems:

SELECT The_Month,SUM(val)

FROM

(

SELECT 1 as the_month ,AMOUNT/MONTHS AS val FROM ROUNDING_PROBLEM

UNION ALL

SELECT 2 the_month ,AMOUNT/MONTHS as val FROM ROUNDING_PROBLEM

UNION ALL

SELECT 3 the_month ,AMOUNT/MONTHS as val FROM ROUNDING_PROBLEM

) x

GROUP BY 1

ORDER BY 1

;

Unfortunately, you will end up with this result:

*The_Month Sum(val)
*1 3,42

2 3,42

3 3,42

**10,26**

** **

As you can see, the result is 10,26, but the sum should be 10,25.

There is no easy solution for this as we only have two digits of the precision available in our table.

Still, there is a solution: create an additional record holding the rounding difference (in my example I added it to the last month):

SELECT The_Month,SUM(val)

FROM

(

SELECT 1 as the_month ,AMOUNT/MONTHS AS val FROM ROUNDING_PROBLEM

UNION ALL

SELECT 2 the_month ,AMOUNT/MONTHS as val FROM ROUNDING_PROBLEM

UNION ALL

SELECT 3 the_month ,AMOUNT/MONTHS as val FROM ROUNDING_PROBLEM

UNION ALL

**SELECT 3, AMOUNT – (AMOUNT/MONTHS*MONTHS) FROM ROUNDING_PROBLEM**

) x

GROUP BY 1

ORDER BY 1

;

*The_Month Sum(val)
*1 3,42

2 3,42

3 3,41

**10,25**

Now we can add up the monthly amounts and will have the correct results in the case of aggregations. On the other hand, we have an additional record available which identifies the rounding differences, and it could be stored with a special identification code to distinguish it from the regular records.