在SQL Server中从十进制中删除尾随零

时间:2010-05-30 10:56:45

标签: sql tsql sql-server-2008 formatting decimal

我有一个列DECIMAL(9,6),即它支持的值为999,123456。

但是当我插入像123,4567这样的数据时,它变成了123,456700

如何删除这些零?

23 个答案:

答案 0 :(得分:123)

decimal(9,6)在逗号的右侧存储6位数字。是否显示尾随零是格式化决策,通常在客户端实现。

但是由于SSMS格式float没有尾随零,您可以通过将decimal转换为float来删除尾随零:

select 
    cast(123.4567 as DECIMAL(9,6))
,   cast(cast(123.4567 as DECIMAL(9,6)) as float)

打印:

123.456700  123,4567

(我的小数点分隔符是一个逗号,但SSMS用点表示十进制。显然是known issue。)

答案 1 :(得分:28)

您可以使用FORMAT()函数(SqlAzure和Sql Server 2012 +):

SELECT FORMAT(CAST(15.12     AS DECIMAL(9,6)), 'g18')  -- '15.12'
SELECT FORMAT(CAST(0.0001575 AS DECIMAL(9,6)), 'g10')  -- '0.000158'
SELECT FORMAT(CAST(2.0       AS DECIMAL(9,6)), 'g15')  -- '2'

使用FLOAT(或REAL)时要小心:不要使用g17或更大(或g8或更大的REAL),因为机器表示的精度有限会导致不必要的影响:

SELECT FORMAT(CAST(15.12 AS FLOAT), 'g17')         -- '15.119999999999999'
SELECT FORMAT(CAST(0.9 AS REAL), 'g8')             -- '0.89999998'
SELECT FORMAT(CAST(0.9 AS REAL), 'g7')             -- '0.9'

此外,请注意,根据documentation

  

FORMAT依赖于.NET Framework公共语言的存在   运行时(CLR)。此功能因其依赖而不会被远程控制   CLR的存在。远程处理需要CLR的功能   会导致远程服务器出错。

也适用于SqlAzure。

答案 2 :(得分:13)

SELECT CONVERT(DOUBLE PRECISION, [ColumnName])

答案 3 :(得分:8)

我不愿意转为浮动,因为我的十进制数字可能比浮点数更多可能代表

FORMAT与标准.net格式字符串' g8'一起使用时在非常小的小数(例如1e-08)的情况下返回科学记数法,这也是不合适的

使用自定义格式字符串(https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings)让我实现了我想要的目标:

DECLARE @n DECIMAL(9,6) =1.23;
SELECT @n
--> 1.230000
SELECT FORMAT(@n, '0.######')
--> 1.23

如果您希望您的号码至少有一个尾随零,那么2.0不会变为2,请使用类似0.0#####的格式字符串

小数点是本地化的,因此使用逗号作为小数分隔符的文化将遇到逗号输出。是

当然,这是让数据层进行格式化的不可行的做法(但在我的情况下,没有其他层;用户实际上是在运行存储过程并将结果放入电子邮件中:/)

答案 4 :(得分:6)

SELECT REVERSE(ROUND(REVERSE(2.5500),1))

打印:

2.55

答案 5 :(得分:3)

Cast(20.5500 as Decimal(6,2))

应该这样做。

答案 6 :(得分:2)

我遇到了类似的问题,需要修剪xx0000,x00000,xxx000

等数字的尾随零

我用过:

select LEFT(code,LEN(code)+1 - PATINDEX('%[1-Z]%',REVERSE(code))) from Tablename

代码是包含要修剪的编号的字段的名称。希望这有助于其他人。

答案 7 :(得分:2)

我有一个类似的问题,但也需要删除没有小数的小数点,这里是我的解决方案,它将小数分成其组件,并根据小数点字符串所需的字符数分数组件的长度(不使用CASE)。为了使问题更加有趣,我的号码被存储为没有小数点的浮点数。

DECLARE @MyNum FLOAT
SET @MyNum = 700000
SELECT CAST(PARSENAME(CONVERT(NUMERIC(15,2),@MyNum/10000),2) AS VARCHAR(10)) 
+ SUBSTRING('.',1,LEN(REPLACE(RTRIM(REPLACE(CAST(PARSENAME(CONVERT(NUMERIC(15,2),@MyNum/10000),1) AS VARCHAR(2)),'0',' ')),' ','0'))) 
+ REPLACE(RTRIM(REPLACE(CAST(PARSENAME(CONVERT(NUMERIC(15,2),@MyNum/10000),1) AS VARCHAR(2)),'0',' ')),' ','0') 

结果很痛苦,我知道,但是我从那里得到了很多帮助。

答案 8 :(得分:2)

最好的方法是在转换之前不转换为 FLOAT MONEY ,因为可能会失去精确度。所以安全的方式可以是这样的:

CREATE FUNCTION [dbo].[fn_ConvertToString]
(
    @value sql_variant
)
RETURNS varchar(max)
AS
BEGIN
    declare @x varchar(max)
    set @x= reverse(replace(ltrim(reverse(replace(convert(varchar(max) , @value),'0',' '))),' ',0))

    --remove "unneeded "dot" if any
    set @x = Replace(RTRIM(Replace(@x,'.',' ')),' ' ,'.')
    return @x
END

其中@value可以是任何十进制(x,y)

答案 9 :(得分:1)

另一种选择......

我不知道这有多高效,但它似乎有效并且不会通过浮动:

select replace(rtrim(replace(
       replace(rtrim(replace(cast(@value as varchar(40)), '0', ' ')), ' ', '0')
       , '.', ' ')), ' ', '.')

中间线剥去尾随空格,如果没有小数位,则外部两个删除点

答案 10 :(得分:1)

我需要删除小数上的尾随零,这样我就可以输出一个只有前导零的特定长度的字符串

(例如,我需要输出14个字符,以便142.023400变为000000142.0234),

我使用parsenamereversecast as int删除了尾随零:

SELECT
    PARSENAME(2.5500,2)
    + '.'
    + REVERSE(CAST(REVERSE(PARSENAME(2.5500,1)) as int))

(然后得到我的前导零,我可以根据上面的长度复制正确数量的零,并将其连接到上面的前面)

我希望这有助于某人。

答案 11 :(得分:0)

在上述所有答案中,我发现只有两个真正有效。不要转换为浮点数,这里证明如果这样做,3.175 将不起作用。

SELECT  round(cast(3.175 as float), 2) as roundingcheck,    
CASE WHEN
    round(cast(3.175 as float), 2) = 3.18 THEN 'PASSED' ELSE 'FAILED' END
    as roundecheck,     
    CAST(round(TRY_CONVERT(DECIMAL(28,2), cast(3.175 as
    float)), 2) as nvarchar(max)) as roundconvert,  
    round(CAST(3.175 as DECIMAL(18,10)), 4) as check1,  
cast(CAST(round(CAST(3.175 as DECIMAL(18,10)), 4) as decimal(18,2)) as nvarchar(max))  as
    roundconvert2,  
cast(CAST(CAST(3.175 as DECIMAL(18,10)) as decimal(18,2)) as nvarchar(max))  as roundconvert3,
cast(CAST(CAST(3.149 as DECIMAL(18,10)) as decimal(18,1)) as nvarchar(max))  as roundconvert4,  
cast(FORMAT(round(CAST(3.175 as
    DECIMAL(18,10)), 2), '0.######') as nvarchar(max))  as roundconvert5

结果:

3.17    FAILED  3.17    3.1750000000    3.18    3.18    3.1    3.18

工作答案:

  • 如果您想同时四舍五入到小数点后两位,请使用:

      cast(CAST(CAST(3.175 as DECIMAL(18,10)) as decimal(18,2)) as nvarchar(max))  as roundconvert3,
    
  • 如果您不知道将有多少个小数,您可以使用它并在需要时将其与 round 一起使用:

     cast(FORMAT(round(CAST(3.175 as DECIMAL(18,10)), 2), '0.######') as nvarchar(max))
    

答案 12 :(得分:0)

最简单的方法是将值CAST为FLOAT,然后再为字符串数据类型。

CAST(CAST(123.456000 AS FLOAT) AS VARCHAR(100))

答案 13 :(得分:0)

试试这个。

select CAST(123.456700 as float),cast(cast(123.4567 as DECIMAL(9,6)) as float)

答案 14 :(得分:0)

我知道这是一篇旧帖子,但想提供我想出的SQL

DECLARE @value DECIMAL(23,3)
set @value = 1.2000
select @value original_val, 
    SUBSTRING(  CAST( @value as VARCHAR(100)), 
                0,
                PATINDEX('%.%',CAST(@value as VARCHAR(100)))
            )
      + CASE WHEN ROUND( 
                        REVERSE( SUBSTRING( CAST(@value as VARCHAR(100)),
                                        PATINDEX('%.%',CAST(@value as VARCHAR(100)))+1,
                                        LEN(CAST(@value as VARCHAR(100)))
                                        )
                                )
                    ,1) > 0 THEN 
            '.' 
            +  REVERSE(ROUND(REVERSE(SUBSTRING( CAST(@value as VARCHAR(100)),
                                                PATINDEX('%.%',CAST(@value as VARCHAR(100)))+1,
                                                LEN(CAST(@value as VARCHAR(100)))
                                                )
                ),1))
        ELSE '' END  AS modified_val

答案 15 :(得分:0)

试试这个:

SELECT REPLACE(TRIM(REPLACE(20.5500, "0", " ")), " ", "0")

给出20.55

答案 16 :(得分:0)

case when left(replace(ltrim(rtrim(replace(str(XXX, 38, 10), '0',  ' '))), ' ', '0'), 1) = '.'
then '0' 
else ''
end +

replace(ltrim(rtrim(replace(str(XXX, 38, 10), '0',  ' '))), ' ', '0') +

case when right(replace(ltrim(rtrim(replace(str(XXX, 38, 10), '0',  ' '))), ' ', '0'), 1) = '.'
then '0' 
else ''
end

答案 17 :(得分:0)

可以删除TSQL中的前导零和尾随零

  1. 如果不是字符串,则使用STR TSQL函数将其转换为字符串,然后

  2. 删除领先&尾随零

    SELECT REPLACE(RTRIM(LTRIM(REPLACE(AccNo,'0',' '))),' ','0') AccNo FROM @BankAccount
    
  3. 有关forum的更多信息。

答案 18 :(得分:0)

这个怎么样?假设数据作为@thisData进入你的函数:

BEGIN
  DECLARE @thisText VARCHAR(255)
  SET @thisText = REPLACE(RTRIM(REPLACE(@thisData, '0', ' ')), ' ', '0')
  IF SUBSTRING(@thisText, LEN(@thisText), 1) = '.'
    RETURN STUFF(@thisText, LEN(@thisText), 1, '')
  RETURN @thisText
END

答案 19 :(得分:-1)

我知道这个帖子已经很老了但是对于那些没有使用SQL Server 2012或更高版本的人来说,或者由于任何原因无法使用FORMAT功能,那么以下工作。

此外,如果数字小于1(例如0.01230000),很多解决方案都无效。

请注意,以下内容不适用于负数。

DECLARE @num decimal(28,14) = 10.012345000
SELECT PARSENAME(@num,2) + REPLACE(RTRIM(LTRIM(REPLACE(@num-PARSENAME(@num,2),'0',' '))),' ','0') 

set @num = 0.0123450000
SELECT PARSENAME(@num,2) + REPLACE(RTRIM(LTRIM(REPLACE(@num-PARSENAME(@num,2),'0',' '))),' ','0') 

分别返回10.012345和0.012345。

答案 20 :(得分:-1)

试试这个:

select isnull(cast(floor(replace(rtrim(ltrim('999,999.0000')),',','')) as int),0)

答案 21 :(得分:-1)

DECIMAL(9,6)列将转换为float而不会丢失精度,因此CAST(... AS float)将完成这一操作。

@HLGEM:说浮动是存储数字的不良选择,而且#34;永远不要使用浮动"是不正确的 - 你只需要知道你的号码,例如温度测量可以很好地作为漂浮物。

@abatishchev和@japongskie:如果不需要,SQL存储过程和函数前面的前缀仍然是个好主意;您提到的链接仅指示不使用" sp _"您不应该使用的存储过程的前缀,其他前缀很好,例如" USP _"或" spBob _"

参考: "具有6个或更少有效十进制数字的所有整数都可以转换为IEEE 754浮点值,而不会损失精度":https://en.wikipedia.org/wiki/Single-precision_floating-point_format

答案 22 :(得分:-1)

试试这个:

select Cast( Cast( (ROUND( 35.457514 , 2) *100) as Int) as float ) /100