У меня есть столбец, DECIMAL(9,6)
т.е. он поддерживает такие значения, как 999,123456.
Но когда я вставляю данные типа 123,4567, они становятся 123,456700
Как убрать эти нули?
У меня есть столбец, DECIMAL(9,6)
т.е. он поддерживает такие значения, как 999,123456.
Но когда я вставляю данные типа 123,4567, они становятся 123,456700
Как убрать эти нули?
Ответы:
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
или больше с 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'
Кроме того, обратите внимание, что согласно документации :
FORMAT зависит от наличия среды CLR .NET Framework. Эта функция не будет удалена, так как она зависит от наличия среды CLR. Удаление функции, для которой требуется CLR, вызовет ошибку на удаленном сервере.
Также работает в SqlAzure.
SELECT CONVERT(DOUBLE PRECISION, [ColumnName])
Я не хотел приводить к типу float из-за того, что в моей десятичной дроби может быть больше цифр, чем может представлять 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#####
Десятичная точка локализована, поэтому в культурах, в которых в качестве десятичного разделителя используется запятая, будет выводиться запятая, где расширение. является
Конечно, это обескураживающая практика, когда уровень данных выполняет форматирование (но в моем случае другого слоя нет; пользователь буквально запускает хранимую процедуру и отправляет результат по электронной почте: /)
SELECT REVERSE(ROUND(REVERSE(2.5500),1))
печатает:
2.55
Cast(20.5500 as Decimal(6,2))
должен это сделать.
Попробуй это :
SELECT REPLACE(TRIM(REPLACE(20.5500, "0", " ")), " ", "0")
Дает 20,55
0.000
стал .
. вот исправление SELECT REPLACE(RTRIM(REPLACE(20.5500, "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 или 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)
sp_
для хранимых процедур, fn_
для функций, tbl
для таблиц и т. д. на ... это не требование, но это лучший способ организации наших баз данных.
У меня была аналогичная проблема, мне нужно было обрезать конечные нули из чисел вроде xx0000,x00000,xxx000
Я использовал:
select LEFT(code,LEN(code)+1 - PATINDEX('%[1-Z]%',REVERSE(code))) from Tablename
Код - это имя поля, номер которого нужно обрезать. Надеюсь, это поможет кому-то другому.
Другой вариант...
Я не знаю, насколько это эффективно, но похоже, что он работает и не проходит через float:
select replace(rtrim(replace(
replace(rtrim(replace(cast(@value as varchar(40)), '0', ' ')), ' ', '0')
, '.', ' ')), ' ', '.')
Средняя линия удаляет конечные пробелы, две внешние удаляют точку, если нет десятичных цифр.
Мне нужно было удалить конечные нули в моих десятичных числах, чтобы я мог вывести строку определенной длины только с ведущими нулями
(например, мне нужно было вывести 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
Больше информации на форуме .
REPLACE(RTRIM(REPLACE(REPLACE(RTRIM(REPLACE(X,'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
попробуй это.
select CAST(123.456700 as float),cast(cast(123.4567 as DECIMAL(9,6)) as float)
Попробуй это:
select Cast( Cast( (ROUND( 35.457514 , 2) *100) as Int) as float ) /100
Я знаю, что этот поток очень старый, но для тех, кто не использует 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 соответственно.
Попробуй это:
select isnull(cast(floor(replace(rtrim(ltrim('999,999.0000')),',','')) as int),0)
999999
, OP просит удалить конечные нули.
Столбец DECIMAL (9,6) преобразуется в число с плавающей запятой без потери точности, поэтому CAST (... AS float) поможет.
@HLGEM: сказать, что float - плохой выбор для хранения чисел, а «Никогда не использовать float» неверно - вам просто нужно знать свои числа, например, измерения температуры будут хорошо проходить как поплавки.
@abatishchev и @japongskie: префиксы перед сохраненными процедурами и функциями SQL по-прежнему являются хорошей идеей, если не требуются; упомянутые вами ссылки только инструктируют не использовать префикс «sp_» для хранимых процедур, которые вы не должны использовать, другие префиксы подходят, например, «usp_» или «spBob_»
Ссылка: «Все целые числа с 6 или менее значащими десятичными знаками могут быть преобразованы в значение с плавающей запятой IEEE 754 без потери точности»: https://en.wikipedia.org/wiki/Single-precision_floating-point_format