Comment convertir float en varchar dans SQL Server

130

J'ai une colonne flottante avec des nombres de longueur différente et j'essaye de les convertir en varchar.

Certaines valeurs dépassent la taille maximale de bigint, donc je ne peux pas faire quelque chose comme ça

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

J'ai essayé d'utiliser la décimale, mais les nombres ne sont pas de la même taille, donc cela n'aide pas trop

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

Toute aide est appréciée.

METTRE À JOUR:

La valeur de l'échantillon est 2,2000012095022E + 26 .

hgulyan
la source
cast(float_field as varchar(max))sinon je ne comprends pas la question
Denis Valeev
5
la valeur de votre casting est de 2,2e + 026. Vous n'obtenez probablement pas la question :)
hgulyan

Réponses:

247

Essayez d'utiliser la STR()fonction.

SELECT STR(float_field, 25, 5)

Fonction STR ()


Autre remarque: ce pad sur la gauche avec des espaces. Si c'est un problème, combinez avec LTRIM:

SELECT LTRIM(STR(float_field, 25, 5))
codingbadger
la source
3
J'ai eu ************************* . Qu'est-ce que c'est? :)
hgulyan
4
@hgulyan - Fonctionne-t-il Select LTRIM(Str(float_field, 38, 0))pour vos données?
Martin Smith
@Martin Smith, cela semble fonctionner, mais de la même manière que le décimal, donc je ne suis pas sûr que ce soit la valeur réelle (les dix derniers chiffres sont zéro). Je suppose que la valeur réelle a été perdue. Je vous remercie!
hgulyan
2
@hgulyan - les dix derniers chiffres sont nuls car c'est à cela que sert le dernier paramètre de la Strfonction. Le nombre de chiffres après la virgule décimale. Avez-vous lu le lien que j'ai publié? Changez le zéro en 10. Select LTRIM(Str(float_field, 38, 10))
codingbadger
4
J'aurais aimé qu'il y ait un avertissement dans SSMS "hé, quand vous convertissez ce champ de téléphone flottant erroné en texte, soyez prêt à obtenir un joli numéro de téléphone avec une notation scientifique! Nous ne sommes pas assez intelligents pour ltrim (str) d'abord" ...
pkExec
42

Le seul bit de requête que j'ai trouvé qui renvoie le même numéro d'origine EXACT est

CONVERT (VARCHAR(50), float_field,128)

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

Les autres solutions ci-dessus arrondiront parfois ou ajouteront des chiffres à la fin

MISE À JOUR : selon les commentaires ci-dessous et ce que je peux voir dans https://msdn.microsoft.com/en-us/library/ms187928.aspx :

CONVERT (VARCHAR(50), float_field,3)

Doit être utilisé dans les nouvelles versions de SQL Server (Azure SQL Database et à partir de SQL Server 2016 RC3)

adinas
la source
2
+1 pour @adinas, la valeur flottante est convertie telle quelle, mais à l'exception de la 0valeur flottante convertie en 0.0E0. J'avais besoin de convertir le champ float en varchartant que je dois l'afficher NAquand NULLet 0tel quel. J'ai réalisé cela en ajoutant une CASEdéclaration dans la requête comme ci-dessous; 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
Selon le document sur Microsoft - msdn.microsoft.com/en-us/library/ms187928.aspx , la syntaxe 128 est incluse pour des raisons d'héritage et pourrait être déconseillée dans une version future
Mike Turner
1
128 est obsolète mais 3 semble le remplacer dans les versions les plus récentes de SQL Server.
user3524983
13

c'est la solution que j'ai fini par utiliser dans sqlserver 2012 (puisque toutes les autres suggestions avaient l'inconvénient de tronquer une partie fractionnaire ou un autre inconvénient).

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

production:

1000000000.1234

cela a l'avantage supplémentaire (dans mon cas) de faciliter le séparateur de milliers et la localisation:

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

production:

1.000.000.000,1234
moléculaire
la source
3

Sujet utile merci.

Si vous voulez comme moi supprimer les leadings zéro, vous pouvez l'utiliser:

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

float n'a qu'un max. précision de 15 chiffres. Les chiffres après la 15e position sont donc aléatoires et la conversion en bigint (max. 19 chiffres) ou décimale ne vous aide pas.

devio
la source
Je ne comprends pas. La valeur du champ est 2,2000012095022E + 26. Quelle est la solution? Il n'y en a pas?
hgulyan
vous ne pouvez pas obtenir plus de chiffres en convertissant en chaîne qu'il n'y a de chiffres stockés dans la valeur d'origine.
devio
Alors j'ai perdu des chiffres après la 15e position?
hgulyan
Il y avait une sorte de problème avec les données. J'ai juste besoin de mettre à jour cette valeur avec un flottant à 15 chiffres. J'accepte votre réponse, car elle décrit le problème principal que j'ai rencontré avec ces données. Je vous remercie.
hgulyan
2

Cela peut aider sans arrondir

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
la source
2

Convertissez en un integerpremier puis en un string:

cast((convert(int,b.tax_id)) as varchar(20))
Amit Patil
la source
Cela supprimera les chiffres après la virgule, le cas échéant. Par conséquent, cette solution n'est pas exacte.
RushabhG
2

Essayez celui-ci, devrait fonctionner:

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

Si vous utilisez une fonction CLR, vous pouvez convertir le float en une chaîne qui ressemble exactement au float, sans tous les 0 supplémentaires à la fin.

Fonction 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; }
}

.

Exemple

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

.

Production

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

.

Caveat

Toutes les chaînes converties sont tronquées à 18 décimales et il n'y a pas de zéros de fin. 18 chiffres de précision ne sont pas un problème pour nous. Et, 100% de nos nombres FP (près de 100 000 valeurs) semblent identiques en tant que valeurs de chaîne comme ils le font dans la base de données en tant que nombres FP.

James L.
la source
0

La réponse d'Axel modifiée un peu car elle produira dans certains cas des résultats indésirables.

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'),'.',' ')),' ','.')
user2388752
la source
0
select replace(myFloat, '', '')

de la documentation de REPLACE () :

Renvoie nvarchar si l'un des arguments d'entrée est du type de données nvarchar; sinon, REPLACE renvoie varchar.
Renvoie NULL si l'un des arguments est NULL.

tests:
nul ==> [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

Dinah
la source
0

Sélectionnez
cast (replace (convert (decimal (15,2), acs_daily_debit), '.', ',') As varchar (20))

depuis acs_balance_details

Eduardo
la source
0

Basé sur la réponse moléculaire:

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;
user8642458
la source
0

Je viens de rencontrer une situation similaire et j'ai été surpris par les problèmes d'arrondi des `` très grands nombres '' présentés dans SSMS v17.9.1 / SQL 2017.

Je ne suggère pas d'avoir une solution, cependant j'ai observé que FORMAT présente un nombre qui semble correct. Je ne peux pas dire que cela réduit les problèmes d'arrondi ou est utile dans une fonction mathématique compliquée.

T Code SQL fourni qui devrait clairement démontrer mes observations tout en permettant aux autres de tester leur code et leurs idées en cas de besoin.

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]
Andrew
la source
0
SELECT LTRIM(STR(float_field, 25, 0))

est la meilleure façon de ne pas ajouter .0000de chiffre à la fin de la valeur.

RUBEN
la source