Reputation: 17
I have a numeric column, and each number has at least 5 decimals. The examples are in below.
How to round the column off to 2 decimals, while maintaining the sum of the first 3 numbers and sum of the last two numbers equal to 100.00 in SQL Server?
Numbers
22.41489
57.34326
20.24185
73.50463
26.49537
I have tested some sql. For example,
select cast(round('22.41489',2) as decimal(18,2)) as a, cast(round('57.34326',2) as decimal(18,2)) as b
,cast(round('20.24185',2) as decimal(18,2)) as c, cast(round('73.50463',2) as decimal(18,2)) as d
, cast(round('26.49537',2) as decimal(18,2)) as e
The sum of a, b, c will be 99.99. Since all the numbers are in the same column, I need to apply the same transformation to all the numbers. I cannot use transformation 1 for the first 3 numbers and apply transformation 2 for the last 2 numbers.
Thanks
Upvotes: 1
Views: 8132
Reputation: 465
If I understand your question correctly, you want to round your numbers down to 2 decimal places but you still want the sum to be the same. That's not going to always hold true. For example, if I add these 5 numbers:
(1.2, 1.2, 1.2, 1.2, 1.2)
I will get 6, but if I round all the numbers first, then take the sum:
(1.0, 1.0, 1.0, 1.0, 1.0)
I will get 5. This is not a limitation in SQL Server, this is just mathematics.
For your business case I would see if you can "round" and "sum" the numbers on whatever front end you are using (e.g. Reporting Services, Excel, etc) where it has the freedom to truncate decimal places while maintaining the precision behind the scenes if you do aggregate the values.
If that's not an option, return both the rounded/formatted value and the full precision value. Use the rounded/formatted value for UI/Display purposes, and use the full precision value for further aggregation.
CREATE TABLE NumberTable
(
Number numeric(10,5)
);
INSERT INTO NumberTable
VALUES
(22.41489),
(57.34326),
(20.24185),
(73.50463),
(26.49537);
SELECT Number,
Cast(Round(Number*100,0)/100.00 as numeric(5,2)) RoundedNumber,
Format(Number,'0.00') FormattedNumber
FROM NumberTable
Upvotes: 0
Reputation: 819
you can use round() function , even after sum
look at this Fiddle
Upvotes: 0
Reputation: 26694
You can use Window Functions to add the missing portion to the number that lost the most during rounding. Like this:
declare @T table (grp int, num numeric(10,5))
insert into @T (grp, num) values
(1, 22.41489),
(1, 57.34326),
(1, 20.24185),
(2, 73.50463),
(2, 26.49537)
select
grp,
num as original_number,
round(num, 2) +
case when 1 = row_number() over (partition by grp order by num - round(num, 2) desc)
then (100 - sum(round(num, 2)) over (partition by grp))
else 0
end as modified_number
from @T
Results
1 22.41489 22.42000
1 57.34326 57.34000
1 20.24185 20.24000
2 73.50463 73.50000
2 26.49537 26.50000
Upvotes: 4