Cómo convertir flotante a varchar en SQL Server

130

Tengo una columna flotante con números de diferente longitud y estoy tratando de convertirlos a varchar.

Algunos valores exceden el tamaño máximo de bigint, así que no puedo hacer algo como esto

cast(cast(float_field as bigint) as varchar(100))

Intenté usar decimal, pero los números no son del mismo tamaño, por lo que esto tampoco ayuda

CONVERT(varchar(100), Cast(float_field as decimal(38, 0)))

Cualquier ayuda es apreciada.

ACTUALIZAR:

El valor de la muestra es 2.2000012095022E + 26 .

hgulyan
fuente
cast(float_field as varchar(max))de lo contrario no tengo la pregunta
Denis Valeev
55
El valor de su lanzamiento es 2.2e + 026. Probablemente no consigas la pregunta :)
hgulyan

Respuestas:

246

Intenta usar la STR()función.

SELECT STR(float_field, 25, 5)

Función STR ()


Otra nota: esto rellena a la izquierda con espacios. Si esto es un problema, combine con LTRIM:

SELECT LTRIM(STR(float_field, 25, 5))
codingbadger
fuente
3
Tengo ************************* . ¿Que es eso? :)
hgulyan
44
@hgulyan - ¿Funciona Select LTRIM(Str(float_field, 38, 0))para tus datos?
Martin Smith
@ Martin Smith, parece funcionar, pero de la misma manera que el decimal, así que no estoy seguro de si es el valor real (los últimos diez dígitos son cero). Supongo que se perdió el valor real. ¡Gracias!
hgulyan
2
@hgulyan: los últimos diez dígitos son cero porque para eso está el último parámetro en la Strfunción. El número de dígitos después del punto decimal. ¿Leíste el enlace que publiqué? Cambie el cero a 10. Select LTRIM(Str(float_field, 38, 10))
codingbadger
44
Desearía que hubiera una advertencia en SSMS "oye, cuando conviertes ese campo de teléfono flotante erróneo en texto, ¡prepárate para obtener un buen número de teléfono con notación científica! No somos lo suficientemente inteligentes como para ltrim (str) primero" ...
pkExec
42

El único bit de consulta que encontré que devuelve el mismo número original EXACT es

CONVERT (VARCHAR(50), float_field,128)

Ver http://www.connectsql.com/2011/04/normal-0-microsoftinternetexplorer4.html

Las otras soluciones anteriores a veces redondean o agregan dígitos al final

ACTUALIZACIÓN : Según los comentarios a continuación y lo que puedo ver en https://msdn.microsoft.com/en-us/library/ms187928.aspx :

CONVERT (VARCHAR(50), float_field,3)

Debe usarse en nuevas versiones de SQL Server (Azure SQL Database, y comenzando en SQL Server 2016 RC3)

adinas
fuente
2
+1 para @adinas, el valor flotante se convierte como tal pero con la excepción del 0valor flotante convertido como 0.0E0. Necesitaba convertir el campo flotante a varcharcomo necesito mostrar NAcuándo NULLy 0cómo es. Lo logré agregando una CASEdeclaración en la consulta como se muestra a continuación; 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
2
De acuerdo con el documento de Microsoft: msdn.microsoft.com/en-us/library/ms187928.aspx , la sintaxis de 128 está incluida por razones heredadas y puede ser eliminada en una versión futura
Mike Turner,
1
128 está en desuso pero 3 parece ser su reemplazo en las versiones más recientes de SQL Server.
user3524983
13

Esta es la solución que terminé usando en sqlserver 2012 (ya que todas las otras sugerencias tenían el inconveniente de truncar la parte fraccional o algún otro inconveniente).

declare @float float = 1000000000.1234;
select format(@float, N'#.##############################');

salida:

1000000000.1234

Esto tiene la ventaja adicional (en mi caso) de facilitar la separación y la localización de miles:

select format(@float, N'#,##0.##########', 'de-DE');

salida:

1.000.000.000,1234
molecular
fuente
3

Tema útil gracias.

Si desea que yo elimine los encabezados cero, puede usar eso:

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

flotador solo tiene un máx. precisión de 15 dígitos. Por lo tanto, los dígitos después de la posición 15 son aleatorios, y la conversión a bigint (máx. 19 dígitos) o decimal no le ayuda.

devio
fuente
No lo entiendo El valor del campo es 2.2000012095022E + 26. ¿Cual es la solución? No hay ninguno?
hgulyan
no puede obtener más dígitos al convertir en cadena que los dígitos almacenados en el valor original.
devio
¿Entonces he perdido dígitos después de la 15ª posición?
hgulyan
Hubo algún tipo de problema con los datos. Solo necesito actualizar ese valor con un flotante de 15 dígitos. Aceptaré tu respuesta, porque describe el problema principal que tuve con estos datos. Gracias.
hgulyan
2

Esto puede ayudar sin redondear

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)
Atul
fuente
2

Convierte en un integerprimero y luego en un string:

cast((convert(int,b.tax_id)) as varchar(20))
Amit Patil
fuente
Esto eliminará los dígitos después del decimal, si corresponde. Por lo tanto, esta solución no es precisa.
RushabhG
2

Prueba este, debería funcionar:

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

Si usa una función CLR, puede convertir el flotante en una cadena que se parezca al flotante, sin todos los 0 adicionales al final.

Función 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; }
}

.

Ejemplo

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

.

Salida

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

.

Consideración

Todas las cadenas convertidas se truncan a 18 decimales, y no hay ceros finales. 18 dígitos de precisión no son un problema para nosotros. Y, el 100% de nuestros números FP (cerca de 100,000 valores) se ven idénticos como valores de cadena como lo hacen en la base de datos como números FP.

James L.
fuente
0

La respuesta de Axel modificada un poco ya que para ciertos casos producirá resultados indeseables.

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'),'.',' ')),' ','.')
usuario2388752
fuente
0
select replace(myFloat, '', '')

de la documentación REPLACE () :

Devuelve nvarchar si uno de los argumentos de entrada es del tipo de datos nvarchar; de lo contrario, REPLACE devuelve varchar.
Devuelve NULL si alguno de los argumentos es NULL.

pruebas:
nulo ==> [NULO]
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

Dinah
fuente
0

Seleccione
cast (replace (convert (decimal (15,2), acs_daily_debit), '.', ',') Como varchar (20))

de acs_balance_details

Eduardo
fuente
0

Basado en la respuesta molecular:

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;
usuario8642458
fuente
0

Acabo de encontrar una situación similar y me sorprendieron los problemas de redondeo de 'números muy grandes' presentados en SSMS v17.9.1 / SQL 2017.

No estoy sugiriendo que tenga una solución, sin embargo, he observado que FORMAT presenta un número que parece correcto. No puedo dar a entender que esto reduce más problemas de redondeo o es útil dentro de una función matemática complicada.

Se suministró un código SQL que debe demostrar claramente mis observaciones al tiempo que permite a otros probar su código e ideas en caso de necesidad.

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]
Andrés
fuente
0
SELECT LTRIM(STR(float_field, 25, 0))

es la mejor manera de no agregar .0000ningún dígito al final del valor.

RUBEN
fuente