Как преобразовать float в varchar в SQL Server


130

У меня есть столбец с плавающей запятой с числами разной длины, и я пытаюсь преобразовать их в 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))иначе я не понимаю вопроса
Денис Валеев

5
значение для вашего броска составляет 2.2e + 026. Наверное, вы не уловили вопрос :)
хгулян

Ответы:


248

Попробуйте воспользоваться STR()функцией.

SELECT STR(float_field, 25, 5)

STR () Функция


Еще одно примечание: это прокладки слева с пробелами. Если это проблема, совместите с LTRIM:

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

3
Я получил ************************* . Что это такое? :)
hgulyan

4
@hgulyan - У Select LTRIM(Str(float_field, 38, 0))ваших данных работает?
Мартин Смит

@Martin Smith, вроде работает, но так же, как десятичный, поэтому я не уверен, настоящее ли это значение (последние десять цифр равны нулю). Думаю, реальная ценность была потеряна. Спасибо!
hgulyan

2
@hgulyan - последние десять цифр равны нулю, потому что это последний параметр Strфункции. Количество цифр после десятичной точки. Вы прочитали ссылку, которую я разместил? Измените ноль на 10. Select LTRIM(Str(float_field, 38, 10))
codingbadger

4
Хотелось бы, чтобы в SSMS было предупреждение «эй, когда вы конвертируете это ошибочное поле телефона с плавающей запятой в текст, будьте готовы получить хороший телефонный номер с научным обозначением! Мы недостаточно умны, чтобы сначала ltrim (str)» ...
pkExec

42

Единственный бит запроса, который я обнаружил, который возвращает ТОЧНО такое же исходное число, это

CONVERT (VARCHAR(50), float_field,128)

См. Http://www.connectsql.com/2011/04/normal-0-microsoftinternetexplorer4.html

Другие решения, приведенные выше, иногда округляют или добавляют цифры в конце

ОБНОВЛЕНИЕ : в соответствии с комментариями ниже и тем, что я вижу в https://msdn.microsoft.com/en-us/library/ms187928.aspx :

CONVERT (VARCHAR(50), float_field,3)

Следует использовать в новых версиях SQL Server (База данных SQL Azure и начиная с SQL Server 2016 RC3)


2
+1 для @adinas, значение с плавающей запятой преобразуется как оно, но за исключением 0значения с плавающей запятой, конвертируемого как 0.0E0. Мне нужно было преобразовать поле с плавающей запятой так, varcharкак мне нужно отображать, NAкогда NULLи 0как оно есть. Я добился этого, добавив 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
fujiFX 02

2
Согласно документу Microsoft - msdn.microsoft.com/en-us/library/ms187928.aspx , синтаксис 128 включен по устаревшим причинам и может быть удален в будущей версии
Майк Тернер,

1
128 устарел, но 3, похоже, заменяет его в самых последних выпусках SQL Server.
user3524983

13

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

3

Полезная тема спасибо.

Если вы хотите, как я, удалить нулевые лидеры, вы можете использовать это:

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

2

поплавок имеет только макс. точность до 15 цифр. Следовательно, цифры после 15-й позиции случайны, и преобразование в bigint (макс. 19 цифр) или десятичное число вам не поможет.


Я не понимаю. Значение поля - 2.2000012095022E + 26. Какое решение? Нет?
hgulyan

преобразовав в строку, вы не сможете получить больше цифр, чем хранится в исходном значении.
devio

Значит, я потерял цифры после 15 позиции?
hgulyan

Возникла какая-то проблема с данными. Мне просто нужно обновить это значение с помощью 15-значного числа с плавающей запятой. Я принимаю ваш ответ, потому что он описывает основную проблему, с которой я столкнулся с этими данными. Спасибо.
hgulyan

2

Это может помочь без округления

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)

2

Преобразуйте integerсначала в, а затем в string:

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

Это удалит цифры после десятичной дроби, если они есть. Следовательно, это решение не является точным.
RushabhG

2

Попробуйте это, должно работать:

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

1

Если вы используете функцию CLR, вы можете преобразовать float в строку, которая выглядит так же, как float, без лишних нулей в конце.

Функция 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.


0

Немного изменен ответ Акселя, так как в некоторых случаях он будет давать нежелательные результаты.

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'),'.',' ')),' ','.')

0
select replace(myFloat, '', '')

из документации REPLACE () :

Возвращает nvarchar, если один из входных аргументов имеет тип данных nvarchar; в противном случае REPLACE возвращает varchar.
Возвращает NULL, если любой из аргументов равен NULL.

тесты:
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


0

Выберите
приведение (замените (convert (decimal (15,2), acs_daily_debit), '.', ',') Как varchar (20))

из acs_balance_details


0

На основании молекулярного ответа:

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;

0

Я столкнулся с похожей ситуацией и был удивлен проблемами округления «очень больших чисел», представленными в 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]

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

это лучший способ, чтобы вы не добавляли .0000никаких цифр в конце значения.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.