DECLARE @TAX VARCHAR(30)=120.45
DECLARE @TaxRoundOf VARCHAR(30)
SET @TaxRoundOf=ROUND(@TAX,1)
SELECT @TaxRoundOf
这给出了结果(@TaxRoundOf=120.5(
DECLARE @TAX VARCHAR(30)=146.45
DECLARE @TaxRoundOf VARCHAR(30)
SET @TaxRoundOf=ROUND(@TAX,1)
SELECT @TaxRoundOf
这给出了结果(@TaxRoundOf=146.4(
但是我需要返回146.50
. 为什么两个结果不匹配? 有人可以帮忙吗?
由于您使用VARCHAR
来存储数字,SQL Server 必须进行隐式转换以在幕后浮动,这会对您的计算产生连锁反应。您可以使用以下查询重现此内容:
SELECT ROUND(CONVERT(FLOAT, 120.45),1), -- 120.5
ROUND(CONVERT(FLOAT, 146.45),1), -- 146.4
ROUND(CONVERT(DECIMAL(10, 2), 120.45),1), -- 120.50
ROUND(CONVERT(DECIMAL(10, 2), 146.45),1) -- 146.50
由于浮点数不精确,146.45 不能精确地表示为浮点数,最终被存储为一个非常小的数字,因此当它传递给 round 函数时,它会向下舍入,而不是向上舍入。
如上述查询中的第 3 列和第 4 列所示,解决方案是使用更精确的数据类型。
你可以使用这个:
SET @TaxRoundOf=ROUND(10 * CAST(@TAX AS FLOAT)) / 10
而不是:
SET @TaxRoundOf=ROUND(@TAX,1)
演示
PS 正如@GarethD已经提到的,我不会将@TAX
用作VARCHAR
类型。
你也可以依靠舍入numeric
而不是将字符串转换为float
,这可能会丢失信息。
将字符串转换为numeric
然后舍入:
select round(cast('146.45' as numeric(18,2)), 1)
-- 146.50
十进制常量已经是一个decimal
所以没有必要强制转换它:
select round(146.45, 1)
-- 146.50