I had a need to be able to calculate banker's rounding directly within a SQL SELECT statement. After searching here and elsewhere on the internet I could not find a solution. So I worked out how to do this and am posting my solution here for others who may have a similar need.
Banker's rounding rounds a terminal 5 to the nearest even number in the next position instead of the next higher number as in conventional rounding. For more on banker's rounding see for example:
I was able to find a number of suggestions for calculating banker's rounding in a formula that can be called from a SELECT, but not directly within the SELECT itself. Below is a way to do that. This technique could also be used in a formula.
select dec, value,
round(value+((mod(trunc(power(10,dec)*value),2)-sign(value))*power(10,-length(value-trunc(value)))),dec) "Banker's Round"
from
(
select 2 dec, 0 value from dual union all
select -2, 1650 from dual union all
select -2, 1750 from dual union all
select -3, 23500 from dual union all
select -3, 24500 from dual union all
select -2, -1650 from dual union all
select -2, -1750 from dual union all
select -3, -23500 from dual union all
select -3, -24500 from dual union all
select 2, 7.345 from dual union all
select 2, 3.454 from dual union all
select 2, 3.455 from dual union all
select 2, 3.445 from dual union all
select 2, 3.456 from dual union all
select 2, 3.4543 from dual union all
select 2, 3.4546 from dual union all
select 2, 3.4653 from dual union all
select 2, 3.4656 from dual union all
select 2, 3.4643 from dual union all
select 2, 3.4646 from dual union all
select 8, 3.445657545 from dual union all
select 2, 3.445 from dual union all
select 2, 3.435 from dual union all
select 2, 3.425 from dual union all
select 2, 3.415 from dual union all
select 2, 3.405 from dual union all
select 2, 3.395 from dual union all
select 2, -7.345 value from dual union all
select 2, -3.454 from dual union all
select 2, -3.455 from dual union all
select 2, -3.445 from dual union all
select 2, -3.456 from dual union all
select 2, -3.4543 from dual union all
select 2, -3.4546 from dual union all
select 2, -3.4653 from dual union all
select 2, -3.4656 from dual union all
select 2, -3.4643 from dual union all
select 2, -3.4646 from dual union all
select 8, -3.445657545 from dual union all
select 2, -3.445 from dual union all
select 2, -3.435 from dual union all
select 2, -3.425 from dual union all
select 2, -3.415 from dual union all
select 2, -3.405 from dual union all
select 2, -3.395 from dual
)
Banker's rounding rounds a terminal 5 to the nearest even number in the next position instead of the next higher number as in conventional rounding. For more on banker's rounding see for example:
I was able to find a number of suggestions for calculating banker's rounding in a formula that can be called from a SELECT, but not directly within the SELECT itself. Below is a way to do that. This technique could also be used in a formula.
select dec, value,
round(value+((mod(trunc(power(10,dec)*value),2)-sign(value))*power(10,-length(value-trunc(value)))),dec) "Banker's Round"
from
(
select 2 dec, 0 value from dual union all
select -2, 1650 from dual union all
select -2, 1750 from dual union all
select -3, 23500 from dual union all
select -3, 24500 from dual union all
select -2, -1650 from dual union all
select -2, -1750 from dual union all
select -3, -23500 from dual union all
select -3, -24500 from dual union all
select 2, 7.345 from dual union all
select 2, 3.454 from dual union all
select 2, 3.455 from dual union all
select 2, 3.445 from dual union all
select 2, 3.456 from dual union all
select 2, 3.4543 from dual union all
select 2, 3.4546 from dual union all
select 2, 3.4653 from dual union all
select 2, 3.4656 from dual union all
select 2, 3.4643 from dual union all
select 2, 3.4646 from dual union all
select 8, 3.445657545 from dual union all
select 2, 3.445 from dual union all
select 2, 3.435 from dual union all
select 2, 3.425 from dual union all
select 2, 3.415 from dual union all
select 2, 3.405 from dual union all
select 2, 3.395 from dual union all
select 2, -7.345 value from dual union all
select 2, -3.454 from dual union all
select 2, -3.455 from dual union all
select 2, -3.445 from dual union all
select 2, -3.456 from dual union all
select 2, -3.4543 from dual union all
select 2, -3.4546 from dual union all
select 2, -3.4653 from dual union all
select 2, -3.4656 from dual union all
select 2, -3.4643 from dual union all
select 2, -3.4646 from dual union all
select 8, -3.445657545 from dual union all
select 2, -3.445 from dual union all
select 2, -3.435 from dual union all
select 2, -3.425 from dual union all
select 2, -3.415 from dual union all
select 2, -3.405 from dual union all
select 2, -3.395 from dual
)