Удаление конечных нулей из десятичного числа в SQL Server


колонки DECIMAL(9,6) т. е. он поддерживает такие значения, как 999,123456.

но когда я вставляю данные, как 123,4567 он становится 123,456700

Как удалить эти нули?

22 60

22 ответа:

A 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 форматирует десятичное число с точкой. Видимо,известно выпуск.)

можно использовать 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 или больше с реальным), потому что ограниченная точность представления машины вызывает нежелательные эффекты:

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'

кроме того, обратите внимание, что в соответствии с документация:

формат зависит от наличия общего языка .NET Framework Среда выполнения (CLR). Эта функция не будет удалена, так как она зависит от присутствие в среде CLR. Удаленное выполнение функции, для которой требуется среда CLR вызовет ошибку на удаленном сервере.

работает и в SqlAzure.

SELECT CONVERT(DOUBLE PRECISION, [ColumnName])
SELECT REVERSE(ROUND(REVERSE(2.5500),1))

принты:

2.55
Cast(20.5500 as Decimal(6,2))

должны сделать это.

Я не хотел бросать плавать из-за потенциала для большего количества цифр в моей десятичной системе счисления, чем float может представлять

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#####

десятичная точка локализована ,поэтому культуры, которые используют запятую в качестве десятичного разделителя, столкнутся с выходом запятой, где. это

конечно, это обескураживающая практика, когда слой данных выполняет форматирование (но в моем случае нет другого слоя; пользователь буквально запускает хранимую процедуру и размещение результата в электронном письме :/)

У меня была аналогичная проблема, но также требовалось удалить десятичную точку, где не было десятичной точки, вот мое решение, которое разбивает десятичную дробь на ее компоненты и основывает количество символов, которое она берет из строки десятичной точки на длине компонента фракции (без использования 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') 

результат болезненный, я знаю, но я получил там, с большой помощью из ответов выше.

лучший способ не конвертировать в FLOAT или деньги перед преобразованием из-за вероятности потери точности. Таким образом, безопасные способы могут быть примерно такими:

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 может быть любой decimal (x,y)

мне нужно было удалить конечные нули на моих десятичных дробях, чтобы я мог вывести строку определенной длины только с ведущий нули

(например, мне нужно было вывести 14 символов, чтобы 142.023400 стал 000000142.0234),

Я parsename,reverse и castas int чтобы удалить конечные нули:

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

(чтобы затем получить мои ведущие нули, я мог бы воспроизвести правильное количество нулей на основе длины выше и объединить это в передней части выше)

Я надеюсь, что это кому-то поможет.

в TSQL можно удалить начальные и конечные нули

  1. преобразовать его в строку с помощью функции STR TSQL если не строка, то

  2. удалить как начальные, так и конечные нули

    SELECT REPLACE(RTRIM(LTRIM(REPLACE(AccNo,'0',' '))),' ','0') AccNo FROM @BankAccount
    
  3. подробнее о форуме.

попробуйте это :

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

дает 20.55

другой вариант...

Я не знаю, насколько это эффективно, но это, кажется, работает и не проходит через float:

select replace(rtrim(replace(
       replace(rtrim(replace(cast(@value as varchar(40)), '0', ' ')), ' ', '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
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

Я понимаю, что это старый пост, но хотел бы предоставить 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

Я знаю, что этот поток очень старый, но для тех, кто не использует SQL Server 2012 или выше или не может использовать функцию форматирования по какой-либо причине, то следующие работы.

кроме того, многие решения не работали, если число было меньше 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 соответственно.

попробуйте это.

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

самый простой способ-привести значение как FLOAT, а затем к строковому типу данных.

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

у меня была аналогичная проблема, нужно было обрезать конечные нули от чисел, таких как xx0000,x00000,xxx000

Я:

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

код-это имя поля с номером, который нужно обрезать. Надеюсь, это поможет кому-то еще.

десятичный столбец (9,6) преобразуется в float без потери точности, поэтому CAST (... Как поплавок) сделает свое дело.


@HLGEM: говоря, что float является плохим выбором для хранения чисел и "никогда не использовать float" не правильно - вы просто должны знать свои номера, например, измерения температуры будут идти хорошо, как поплавки.

@abatishchev и @japongskie: префиксы перед SQL хранятся procs и функции по-прежнему хорошая идея, если не требуется; ссылки вы упомянутый только инструктирует не использовать префикс " sp_ "для хранимых процедур, которые вы не должны использовать, другие префиксы прекрасны, например" usp_ "или"spBob_"

ссылка: "Все целые числа с 6 или менее значащими десятичными цифрами могут быть преобразованы в значение IEEE 754 с плавающей запятой без потери точности":https://en.wikipedia.org/wiki/Single-precision_floating-point_format

попробуйте это:

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

попробуйте это:

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