Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何计算SQL中的小数位数?_Sql_Sql Server 2008_Floating Point_Decimal_Scale - Fatal编程技术网

如何计算SQL中的小数位数?

如何计算SQL中的小数位数?,sql,sql-server-2008,floating-point,decimal,scale,Sql,Sql Server 2008,Floating Point,Decimal,Scale,我有一个X列,其中充满了小数位数从0(无小数)到6(最大)的浮动。我可以相信这样一个事实,即没有大于小数点后6位的浮点。鉴于此,我如何创建一个新列,以便它告诉我小数点后有多少位数 我看到一些线程建议我使用CAST将浮点转换为字符串,然后解析字符串以计算小数点后的字符串长度。这是最好的方法吗?浮点数只是表示一个实数。实数的小数位数没有意义。特别是实数3可以有六个小数位,3.000000,只是所有的小数位都是零 您可能有一个显示转换,它不显示小数点中最右边的零值 还请注意,小数点后最多有6位的原因是

我有一个X列,其中充满了小数位数从0(无小数)到6(最大)的浮动。我可以相信这样一个事实,即没有大于小数点后6位的浮点。鉴于此,我如何创建一个新列,以便它告诉我小数点后有多少位数


我看到一些线程建议我使用CAST将浮点转换为字符串,然后解析字符串以计算小数点后的字符串长度。这是最好的方法吗?

浮点数只是表示一个实数。实数的小数位数没有意义。特别是实数3可以有六个小数位,3.000000,只是所有的小数位都是零

您可能有一个显示转换,它不显示小数点中最右边的零值

还请注意,小数点后最多有6位的原因是第七位不精确,因此显示转换不会提交到第七位小数

还请注意,浮点以二进制形式存储,它们实际上在二进制点的右侧有二进制位置。十进制显示是浮点存储器中二进制有理数的近似值,而二进制有理数又是实数的近似值


所以问题是,一个浮点值有多少个小数位是没有意义的。如果您转换为字符串(比如使用CAST),则可以计算小数位数。这真的是你想要做的事情的最佳方法。

你可以使用这样的方法:

declare @v sql_variant

set @v=0.1242311

select SQL_VARIANT_PROPERTY(@v, 'Scale') as Scale
这将返回
7


我试图使用
float
列使上述查询正常工作,但未能按预期工作。它只适用于
sql\u变量
列,如下所示:

因此,我开始寻找另一种方法,并以此为基础,我得到了:

SELECT value,
LEN(
    CAST(
         CAST(
              REVERSE(
                      CONVERT(VARCHAR(50), value, 128)
                     ) AS float
             ) AS bigint
        )
   ) as Decimals
FROM Numbers
下面是一个SQL小提琴来测试这一点:


为了解释这个小怪癖,这里有一个修改版本,它将处理浮点值没有小数部分的情况:

SELECT value,
       Decimals = CASE Charindex('.', value)
                    WHEN 0 THEN 0
                    ELSE
           Len (
            Cast(
             Cast(
              Reverse(CONVERT(VARCHAR(50), value, 128)) AS FLOAT
                 ) AS BIGINT
                )
               )
                    END
FROM   numbers

下面是附带的SQL Fiddle:

此线程也在使用CAST,但我发现答案很有趣:

在甲骨文中:

SELECT FLOOR(LOG(10,REVERSE(CAST(ABS(.56544)+1 as varchar(50))))) + 1 from DUAL

下面是另一个Oracle示例。正如我总是在非Oracle用户开始对我大喊大叫和投否决票之前警告他们的那样。。。SUBSTRING和INSTRING是ANSI SQL标准函数,可以在任何SQL中使用。双表可以替换为任何其他表或创建。下面是指向SQL SERVER博客的链接,我从中复制了双表代码:

此查询返回点或小数点后的长度。 如果需要,可以将str转换为_编号(str)。您还可以获取点小数位之前的字符串长度-将代码更改为长度(SUBSTR(str,1,dot_pos))-1,并删除INSTR部分中的+1:

SELECT str, LENGTH(SUBSTR(str, dot_pos)) str_length_after_dot FROM
(
 SELECT '000.000789' as str
      , INSTR('000.000789', '.')+1 dot_pos 
   FROM dual
)
/

SQL>

STR           STR_LENGTH_AFTER_DOT
----------------------------------
000.000789    6

你已经有了关于铸造等方面的答案和例子。

我以前回答过这个问题,但从评论中我可以看出这有点不清楚。随着时间的推移,我找到了更好的表达方式

将pi视为

(a) 3.141592653590
这将pi显示为11位小数。然而,这是四舍五入到12位小数点后,作为pi,14位是正确的

(b) 3.1415926535897932
计算机或数据库以二进制形式存储值。对于单精度浮点,pi将存储为

(c) 3.141592739105224609375
这实际上是向上舍入到单个精度可以存储的最接近的值,就像我们在(a)中舍入一样。单个精度可以存储的下一个最低数字是

(d) 3.141592502593994140625
所以,当你试图计算小数位数时,你试图找到小数位数,在小数位数之后,所有剩余的小数都是零。但是,由于数字可能需要四舍五入才能存储,因此它并不表示正确的值

在进行数学运算时,数字也会引入舍入误差,包括在输入数字时从十进制转换为二进制,以及在显示值时从二进制转换为十进制


您无法可靠地找到数据库中某个数字的小数位数,因为它近似于将其四舍五入以存储在有限的存储空间中。实际值之间的差异,甚至数据库中精确的二进制值之间的差异将被舍入,以十进制表示。舍入过程中可能会丢失更多的十进制数字,因此您不知道什么时候零后面会没有更多的非零数字。

Oracle的解决方案,但您已经想到了。trunc()删除Oracle中的小数部分

select *
from your_table
where (your_field*1000000 - trunc(your_field*1000000)) <> 0;
选择*
从你的桌子上
其中(您的_字段*1000000-trunc(您的_字段*1000000))0;
这个查询的想法是:在你乘以1000000之后,还会有小数吗


选择1.110000,LEN(PARSENAME(Cast(1.110000为float),1))作为十进制后的计数(Count)

很酷的技巧,尽管我认为你的意思是
比例
,而不是
精度
。你能在float列上使用它吗?@TimLehner Afaik不使用直接的SQL查询,
将变量类型设置为7位小数的数字(即存储该值所需的最小值),和
Scale
将返回数据类型的精度,而不是值。当您从表列中选择时,将得到列类型的比例,而不是实际数字的比例。我只是发现了一个小怪癖。如果我的问题中提到了零小数,那么值1、12、123和1234将产生1、2、3和4作为结果事实上,结果应该是0。基本上,如果问题中提到的小数位数为0,则反转并强制转换为bigint来切掉数字是不起作用的。我说的对吗?谢谢。我用CHARINDEX方法得到了一些误报。做
正确(LTRIM(STR(MyColumn,50,10)),10)='0000000000'
检查似乎效果更好。这是一个有趣的想法,但遗憾的是由于TSQL中的默认舍入(浮点到varchar的切分为6位)
(d) 3.141592502593994140625
select *
from your_table
where (your_field*1000000 - trunc(your_field*1000000)) <> 0;