Удаление конечных нулей из десятичного числа в SQL Server
колонки DECIMAL(9,6)
т. е. он поддерживает такие значения, как 999,123456.
но когда я вставляю данные, как 123,4567 он становится 123,456700
Как удалить эти нули?
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.
Я не хотел бросать плавать из-за потенциала для большего количества цифр в моей десятичной системе счисления, чем 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
иcast
as int
чтобы удалить конечные нули:SELECT PARSENAME(2.5500,2) + '.' + REVERSE(CAST(REVERSE(PARSENAME(2.5500,1)) as int))
(чтобы затем получить мои ведущие нули, я мог бы воспроизвести правильное количество нулей на основе длины выше и объединить это в передней части выше)
Я надеюсь, что это кому-то поможет.
в TSQL можно удалить начальные и конечные нули
преобразовать его в строку с помощью функции STR TSQL если не строка, то
удалить как начальные, так и конечные нули
SELECT REPLACE(RTRIM(LTRIM(REPLACE(AccNo,'0',' '))),' ','0') AccNo FROM @BankAccount
подробнее о форуме.
другой вариант...
Я не знаю, насколько это эффективно, но это, кажется, работает и не проходит через 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 соответственно.
самый простой способ-привести значение как 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