[英]How come my SQL code does not correctly count the number of decimal places after the decimal?
SET COUNTDECIMALPLACES =
CASE Charindex('.', NEWNUMBER)
WHEN 0 THEN 0
ELSE
LEN(
CAST(
CAST(
REVERSE( NEWNUMBER ) AS float
) AS bigint
)
)
END
如果数字是222.9375,则将错误地说COUNTDECIMALPLACES =3。但是,如果数字是17.5548,则将正确地说COUNTDECIMALPLACES =4。有人知道为什么吗?
编辑1:要回答评论中的问题,我正在使用SQL Server 2008(MS)。 看起来Gordon Linoff遇到了与我相同的错误。 另外,NEWNUMBER的数据类型为float。 鉴于我有浮点数,所以我的最终目标是计算小数点右边的小数位数。
您的222.9375中有3个,这是因为REVERSE
接受字符串表达式。 通过传递浮点数,SQL Server必须执行从浮点数到varchar的隐式转换。
根据在线书籍:
CAST和CONVERT(Transact-SQL)
浮动和真实风格
当expression为float或real时,style可以是下表中显示的值之一。 其他值被处理为0。值
0(默认)产量
最多6位数字。 适当时以科学计数法使用。
可以使用以下示例将上述定义可视化:
declare @a float = 222.9375, @b float = 12.34564, @c float = 1234564.123456
select convert(varchar, @a, 0) -- Returns 222.938 -- Notice only 6 digits are displayed
, convert(varchar, @b, 0) -- Returns 12.3456 -- Notice only 6 digits are displayed
, convert(varchar, @c, 0) -- Returns 1.23456e+006 -- Notice only 6 digits are displayed
如果您继续使用float作为数据类型,那么即使将float
转换为varchar
并执行字符串操作,也无法期望获得确切的编号。
您甚至不能简单地将float
转换为decimal
因为您不知道要为小数分配多少小数位(小数位)。
或者,如果您以小数开头作为数据类型,则您将自动知道一个数字有多少个小数位,因为您必须声明它。
例如
declare @number decimal(19, 4) = 222.9375
select @number -- 222.9375
让我们更进一步。 要在某种计算后得出小数位数(小数位数),可以使用下面的函数获得答案:
declare @newnumber decimal(19, 4) = 222.9375
select @newnumber * @newnumber -- Returns 49701.1289063
, sql_variant_property(@newnumber * @newnumber, 'scale') -- Returns 7
但是,您很可能无法控制所使用的数据类型,我想到的一种方法是通过结合使用decimal
和varchar
来实现所需的数据。
declare @newnumber float = 222.9375
-- The first 6 columns are just the working steps, solution is in the last column.
select
@newnumber as 'original'
, cast(@newnumber as decimal(38, 18)) as 'decimal' -- Assuming all your numbers can fit in decimal(38, 18).
, cast(cast(@newnumber as decimal(38, 18)) as varchar(max)) as 'varchar'
, reverse(cast(cast(@newnumber as decimal(38, 18)) as varchar(max))) as 'reverse'
, cast(reverse(cast(cast(@newnumber as decimal(38, 18)) as varchar(max))) as decimal(38, 0)) as 'decimal'
, len(cast(reverse(cast(cast(@newnumber as decimal(38, 18)) as varchar(max))) as decimal(38, 0))) as 'len'
, case charindex('.', @newnumber)
when 0 then 0
else len(cast(reverse(cast(cast(@newnumber as decimal(38, 18)) as varchar(max))) as decimal(38, 0)))
end as 'All In One Step'
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.