【问题标题】:How to convert float to varchar in SQL Server如何在 SQL Server 中将浮点数转换为 varchar
【发布时间】:2022-01-17 10:09:27
【问题描述】:

我有一个具有不同长度数字的浮点列,我正在尝试将它们转换为 varchar。

有些值超过了 bigint 最大大小,所以我不能这样做

cast(cast(float_field as bigint) as varchar(100))

我尝试过使用十进制,但数字的大小不同,所以这也无济于事

CONVERT(varchar(100), Cast(float_field as decimal(38, 0)))

感谢任何帮助。

更新:

样本值为2.2000012095022E+26

【问题讨论】:

  • cast(float_field as varchar(max)) 否则我不明白问题
  • 您的演员阵容值为 2.2e+026。可能你没有得到这个问题:)

标签: sql-server-2008


【解决方案1】:
SELECT LTRIM(STR(float_field, 25, 0))

是最好的方法,因此您不要在值的末尾添加.0000 和任何数字。

【讨论】:

    【解决方案2】:

    我刚刚遇到了类似的情况,并对 SSMS v17.9.1 / SQL 2017 中出现的“非常大的数字”的舍入问题感到惊讶。

    我并不是说我有一个解决方案,但是我观察到FORMAT 提出了一个看起来正确的数字。我不能暗示这会减少进一步的舍入问题或在复杂的数学函数中有用。

    提供的 T SQL 代码应该清楚地展示我的观察结果,同时让其他人能够在需要时测试他们的代码和想法。

    WITH Units AS 
    (
       SELECT 1.0 AS [RaisedPower] , 'Ten' As UnitDescription
       UNION ALL
       SELECT 2.0 AS [RaisedPower] , 'Hundred' As UnitDescription
       UNION ALL
       SELECT 3.0 AS [RaisedPower] , 'Thousand' As UnitDescription
       UNION ALL
       SELECT 6.0 AS [RaisedPower] , 'Million' As UnitDescription
       UNION ALL
       SELECT 9.0 AS [RaisedPower] , 'Billion' As UnitDescription
       UNION ALL
       SELECT 12.0 AS [RaisedPower] , 'Trillion' As UnitDescription
       UNION ALL
       SELECT 15.0 AS [RaisedPower] , 'Quadrillion' As UnitDescription
       UNION ALL
       SELECT 18.0 AS [RaisedPower] , 'Quintillion' As UnitDescription
       UNION ALL
       SELECT 21.0 AS [RaisedPower] , 'Sextillion' As UnitDescription
       UNION ALL
       SELECT 24.0 AS [RaisedPower] , 'Septillion' As UnitDescription
       UNION ALL
       SELECT 27.0 AS [RaisedPower] , 'Octillion' As UnitDescription
       UNION ALL
       SELECT 30.0 AS [RaisedPower] , 'Nonillion' As UnitDescription
       UNION ALL
       SELECT 33.0  AS [RaisedPower] , 'Decillion' As UnitDescription
    
    )
    
    SELECT UnitDescription
    
       ,              POWER( CAST(10.0 AS FLOAT(53)) , [RaisedPower] )                                                             AS ReturnsFloat
       ,        CAST( POWER( CAST(10.0 AS FLOAT(53)) , [RaisedPower] )  AS NUMERIC (38,0) )                                        AS RoundingIssues
       , STR(   CAST( POWER( CAST(10.0 AS FLOAT(53)) , [RaisedPower] )  AS NUMERIC (38,0) ) ,   CAST([RaisedPower] AS INT) + 2, 0) AS LessRoundingIssues
       , FORMAT(      POWER( CAST(10.0 AS FLOAT(53)) , [RaisedPower] )  , '0')                                                     AS NicelyFormatted
    
    FROM Units
    ORDER BY [RaisedPower]
    

    【讨论】:

      【解决方案3】:

      根据分子的回答:

      DECLARE @F FLOAT = 1000000000.1234;
      SELECT @F AS Original, CAST(FORMAT(@F, N'#.##############################') AS VARCHAR) AS Formatted;
      
      SET @F = 823399066925.049
      SELECT @F AS Original, CAST(@F AS VARCHAR) AS Formatted
      UNION ALL SELECT @F AS Original, CONVERT(VARCHAR(128), @F, 128) AS Formatted
      UNION ALL SELECT @F AS Original, CAST(FORMAT(@F, N'G') AS VARCHAR) AS Formatted;
      
      SET @F = 0.502184537571209
      SELECT @F AS Original, CAST(@F AS VARCHAR) AS Formatted
      UNION ALL SELECT @F AS Original, CONVERT(VARCHAR(128), @F, 128) AS Formatted
      UNION ALL SELECT @F AS Original, CAST(FORMAT(@F, N'G') AS VARCHAR) AS Formatted;
      

      【讨论】:

        【解决方案4】:

        尝试使用STR() 函数。

        SELECT STR(float_field, 25, 5)
        

        STR() Function


        另一个注意事项:这个在左边用空格填充。如果这是一个问题结合LTRIM:

        SELECT LTRIM(STR(float_field, 25, 5))
        

        【讨论】:

        • 我得到了 ************************* 。那是什么? :)
        • @hgulyan - Select LTRIM(Str(float_field, 38, 0)) 是否适用于您的数据?
        • @Martin Smith,它似​​乎有效,但与十进制相同,所以我不确定它是否是真实值(最后十位数字为零)。我想,真正的价值已经丢失了。谢谢!
        • @hgulyan - 最后十位数字为零,因为这是Str 函数中的最后一个参数。小数点后的位数。你看过我贴的链接吗?将零更改为 10。Select LTRIM(Str(float_field, 38, 10))
        • 我希望 SSMS 中有一个警告“嘿,当您将错误的浮动电话字段转换为文本时,请准备好用科学记数法获得一个漂亮的电话号码!我们不够聪明,无法 ltrim( str) 首先"...
        【解决方案5】:

        试试这个,应该可以的:

        cast((convert(bigint,b.tax_id)) as varchar(20))
        

        【讨论】:

          【解决方案6】:

          这是我最终在 sqlserver 2012 中使用的解决方案(因为所有其他建议都有截断小数部分的缺点或其他一些缺点)。

          declare @float float = 1000000000.1234;
          select format(@float, N'#.##############################');
          

          输出:

          1000000000.1234
          

          这有进一步的优势(在我的例子中)使千位分隔符和本地化变得容易:

          select format(@float, N'#,##0.##########', 'de-DE');
          

          输出:

          1.000.000.000,1234
          

          【讨论】:

            【解决方案7】:

            我发现返回完全相同的原始数字的唯一查询位是

            CONVERT (VARCHAR(50), float_field,128)
            

            http://www.connectsql.com/2011/04/normal-0-microsoftinternetexplorer4.html

            上述其他解决方案有时会在末尾四舍五入或添加数字

            更新:根据下面的 cmets 以及我在 https://msdn.microsoft.com/en-us/library/ms187928.aspx 中看到的内容:

            CONVERT (VARCHAR(50), float_field,3)
            

            应在新的 SQL Server 版本中使用(Azure SQL 数据库,并从 SQL Server 2016 RC3 开始)

            【讨论】:

            • +1 对于@adinas,浮点值按原样转换,但0 浮点值除外,它被转换为0.0E0。我需要将浮点字段转换为varchar,因为我需要在NULL0 时显示NA。我通过在查询中添加CASE 语句来实现这一点,如下所示; CASE WHEN float_field IS NULL THEN 'NA' WHEN float_field = 0 THEN '0' ELSE CONVERT(VARCHAR, float_field, 128) END AS float_As_VChar
            • 根据 Microsoft 上的文档 - msdn.microsoft.com/en-us/library/ms187928.aspx,由于遗留原因,包含 128 语法,并且可能在未来的版本中被弃用
            • 128 已被弃用,但 3 似乎是最新 SQL Server 版本中的替代品。
            • 使用CONVERT (VARCHAR(50), float_field,128) 的建议不准确,引入了舍入错误CONVERT (VARCHAR(50), float_field,3) 没有
            【解决方案8】:

            选择
            cast(replace(convert(decimal(15,2),acs_daily_debit), '.', ',') as varchar(20))

            来自 acs_balance_details

            【讨论】:

              【解决方案9】:

              先转换成integer,再转换成string

              cast((convert(int,b.tax_id)) as varchar(20))
              

              【讨论】:

              • 这将删除小数点后的数字,如果有的话。因此,这个解决方案是不准确的。
              【解决方案10】:

              如果您使用 CLR 函数,您可以将浮点数转换为看起来与浮点数一样的字符串,而末尾没有所有多余的 0。

              CLR 函数

              [Microsoft.SqlServer.Server.SqlFunction(DataAccess = DataAccessKind.Read)]
              [return: SqlFacet(MaxSize = 50)]
              public static SqlString float_to_str(double Value, int TruncAfter)
              {
                string rtn1 = Value.ToString("R");
                string rtn2 = Value.ToString("0." + new string('0', TruncAfter));
              
                if (rtn1.Length < rtn2.Length) { return rtn1; } else { return rtn2; }
              }
              

              .

              示例

              create table #temp (value float)
              insert into #temp values (0.73), (0), (0.63921), (-0.70945), (0.28), (0.72000002861023), (3.7), (-0.01), (0.86), (0.55489), (0.439999997615814)
              
              select value,
                     dbo.float_to_str(value, 18) as converted,
                     case when value = cast(dbo.float_to_str(value, 18) as float) then 1 else 0 end as same
              from   #temp
              
              drop table #temp
              

              .

              输出

              value                  converted                  same
              ---------------------- -------------------------- -----------
              0.73                   0.73                       1
              0                      0                          1
              0.63921                0.63921                    1
              -0.70945               -0.70945                   1
              0.28                   0.28                       1
              0.72000002861023       0.72000002861023           1
              3.7                    3.7                        1
              -0.01                  -0.01                      1
              0.86                   0.86                       1
              0.55489                0.55489                    1
              0.439999997615814      0.439999997615814          1
              

              .

              警告

              所有转换后的字符串都被截断到小数点后 18 位,并且没有尾随零。 18 位精度对我们来说不是问题。而且,我们 100% 的 FP 数字(接近 100,000 个值)看起来与字符串值相同,就像它们在数据库中作为 FP 数字一样。

              【讨论】:

                【解决方案11】:
                select replace(myFloat, '', '')
                

                来自REPLACE() documentation

                如果输入参数之一是 nvarchar 数据类型,则返回 nvarchar;否则,REPLACE 返回 varchar。
                如果任一参数为 NULL,则返回 NULL。

                测试:
                空 ==> [空]
                1.11 ==> 1.11
                1.10 ==> 1.1
                1.00 ==> 1
                0.00 ==> 0
                -1.10 ==> -1.1
                0.00001 ==> 1e-005
                0.000011 ==> 1.1e-005

                【讨论】:

                  【解决方案12】:

                  这有助于不四舍五入

                  declare @test float(25)
                  
                  declare @test1 decimal(10,5)
                  
                  select @test = 34.0387597207
                  select @test
                  set @test1 = convert (decimal(10,5), @test)
                  select cast((@test1) as varchar(12))
                  
                  
                  Select  LEFT(cast((@test1) as varchar(12)),LEN(cast((@test1) as varchar(12)))-1)
                  

                  【讨论】:

                    【解决方案13】:

                    稍微修改了 Axel 的响应,因为它在某些情况下会产生不良结果。

                    DECLARE @MyFloat [float];
                    SET @MyFloat = 1000109360.050;
                    
                    SELECT REPLACE(RTRIM(REPLACE(REPLACE(RTRIM((REPLACE(CAST(CAST(@MyFloat AS DECIMAL(38,18)) AS VARCHAR(max)), '0', ' '))), ' ', '0'),'.',' ')),' ','.')
                    

                    【讨论】:

                      【解决方案14】:

                      有用的话题谢谢。

                      如果你想像我一样删除前导零,你可以使用它:

                      DECLARE @MyFloat [float];
                      SET @MyFloat = 1000109360.050;
                      SELECT REPLACE(RTRIM(REPLACE(REPLACE(RTRIM(LTRIM(REPLACE(STR(@MyFloat, 38, 16), '0', ' '))), ' ', '0'),'.',' ')),' ',',')
                      

                      【讨论】:

                        【解决方案15】:

                        float 只有一个最大值。精度为 15 位。因此,第 15 位之后的数字是随机的,转换为 bigint(最多 19 位)或小数对您没有帮助。

                        【讨论】:

                        • 我不明白。字段值为 2.2000012095022E+26。解决方案是什么?没有吗?
                        • 你不能通过转换为字符串获得比原始值中存储的数字更多的数字。
                        • 所以我在第 15 位之后失去了数字?
                        • 数据存在某种问题。我只需要用 15 位浮点数更新该值。我会接受你的回答,因为它描述了我对这些数据的主要问题。谢谢。
                        猜你喜欢
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2014-04-16
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2019-11-28
                        相关资源
                        最近更新 更多