SQL 服务器奇怪的 ROUND() 行为
SQL Server strange ROUND() behaviour
我有大量 table 的产品行...我只需要它的一小部分数据,更具体地说是产品的价格(正常价格 - 我必须在两个字段之间进行选择从某种意义上说,如果存在一个,我会选择它,否则我会选择另一个;以及销售价格——对于许多产品,销售价格存储为带三位小数的浮点数,因为它是按正常价格的百分比计算的)。所以我设计了适当的查询来实现我想要的,并注意到 ROUND() 函数的一个非常奇怪的行为。
在某些情况下,当小数点后第三位数字为 5(即 .165)时,它会被截断为 .16,而在其他情况下,它会四舍五入为 .17,对于小数点后第三位为 5 的任何其他数字都会发生这种情况当然还有地方!这怎么可能?这是查询:
SELECT CODE, FWHSPRICE, RTLPRICE, CASE WHEN ISNULL(FWHSPRICE, 0) = 0 THEN RTLPRICE ELSE FWHSPRICE END AS REGULAR, ROUND(FLDFLOAT3, 2) AS SALE
FROM MATERIAL
WHERE COMID = 12
AND FLTID1 = 1
这里是两个记录集比较的截图,左边查询中没有 ROUND(),右边查询中有 ROUND()
PS:如果您想让我导出数据进行复制,能否请您向我解释一下如何为您创建合适的 INSERT 语句?整个 table 有很多字段和行,我不知道如何设置 SSMS 来做到这一点。我来自 MySQL,所以 SQL 服务器的这个“领域”对我来说太陌生了...提前谢谢你。
是的,您正在混合两种具有自己的古怪行为(恕我直言)的事物。老实说,除非我需要 float 的特定属性,否则我不会使用 float
,但是如果你坚持使用这种数据类型......
我会先从 float
转换为 decimal
并多一个小数位(甚至可能是 2 位),然后使用另一个转换来舍入而不是舍入本身。例如:
DECLARE @x TABLE(x float);
INSERT @x(x) VALUES(0.615),(0.165),(0.415),(0.414);
SELECT
x,
bad = ROUND(x, 2),
better = CONVERT(decimal(10,2), CONVERT(decimal(10,3), x))
FROM @x;
结果:
x
bad
better
0.615
0.61
0.62
0.165
0.17
0.17
0.415
0.41
0.42
0.414
0.41
0.41
如果您有像 0.4149
这样的值,您可以看到额外的小数位将如何防止四舍五入(除非这是您想要的行为):
DECLARE @f float = 0.4149;
SELECT source = @f,
round_up = CONVERT(decimal(10,2), CONVERT(decimal(10,3), @f)),
round_down = CONVERT(decimal(10,2), CONVERT(decimal(10,4), @f));
结果:
source
round_up
round_down
0.4149
0.42
0.41
我有大量 table 的产品行...我只需要它的一小部分数据,更具体地说是产品的价格(正常价格 - 我必须在两个字段之间进行选择从某种意义上说,如果存在一个,我会选择它,否则我会选择另一个;以及销售价格——对于许多产品,销售价格存储为带三位小数的浮点数,因为它是按正常价格的百分比计算的)。所以我设计了适当的查询来实现我想要的,并注意到 ROUND() 函数的一个非常奇怪的行为。
在某些情况下,当小数点后第三位数字为 5(即 .165)时,它会被截断为 .16,而在其他情况下,它会四舍五入为 .17,对于小数点后第三位为 5 的任何其他数字都会发生这种情况当然还有地方!这怎么可能?这是查询:
SELECT CODE, FWHSPRICE, RTLPRICE, CASE WHEN ISNULL(FWHSPRICE, 0) = 0 THEN RTLPRICE ELSE FWHSPRICE END AS REGULAR, ROUND(FLDFLOAT3, 2) AS SALE
FROM MATERIAL
WHERE COMID = 12
AND FLTID1 = 1
这里是两个记录集比较的截图,左边查询中没有 ROUND(),右边查询中有 ROUND()
PS:如果您想让我导出数据进行复制,能否请您向我解释一下如何为您创建合适的 INSERT 语句?整个 table 有很多字段和行,我不知道如何设置 SSMS 来做到这一点。我来自 MySQL,所以 SQL 服务器的这个“领域”对我来说太陌生了...提前谢谢你。
是的,您正在混合两种具有自己的古怪行为(恕我直言)的事物。老实说,除非我需要 float 的特定属性,否则我不会使用 float
,但是如果你坚持使用这种数据类型......
我会先从 float
转换为 decimal
并多一个小数位(甚至可能是 2 位),然后使用另一个转换来舍入而不是舍入本身。例如:
DECLARE @x TABLE(x float);
INSERT @x(x) VALUES(0.615),(0.165),(0.415),(0.414);
SELECT
x,
bad = ROUND(x, 2),
better = CONVERT(decimal(10,2), CONVERT(decimal(10,3), x))
FROM @x;
结果:
x | bad | better |
---|---|---|
0.615 | 0.61 | 0.62 |
0.165 | 0.17 | 0.17 |
0.415 | 0.41 | 0.42 |
0.414 | 0.41 | 0.41 |
如果您有像 0.4149
这样的值,您可以看到额外的小数位将如何防止四舍五入(除非这是您想要的行为):
DECLARE @f float = 0.4149;
SELECT source = @f,
round_up = CONVERT(decimal(10,2), CONVERT(decimal(10,3), @f)),
round_down = CONVERT(decimal(10,2), CONVERT(decimal(10,4), @f));
结果:
source | round_up | round_down |
---|---|---|
0.4149 | 0.42 | 0.41 |