web-dev-qa-db-fra.com

Supprimer les zéros de fin du nombre décimal dans SQL Server

J'ai une colonne DECIMAL(9,6) c'est-à-dire qu'elle prend en charge des valeurs telles que 999,123456.

Mais quand j'insère des données comme 123,4567, cela devient 123,456700.

Comment supprimer ces zéros?

67
abatishchev

Un decimal(9,6) enregistre 6 chiffres sur le côté droit de la virgule. Le choix d'afficher ou non les zéros de fin est une décision de formatage, généralement appliquée côté client.

Mais puisque les formats SSMS float sans zéros à la fin, vous pouvez supprimer les zéros à la fin en convertissant la decimal en une float:

select 
    cast(123.4567 as DECIMAL(9,6))
,   cast(cast(123.4567 as DECIMAL(9,6)) as float)

impressions:

123.456700  123,4567

(Mon séparateur décimal est une virgule, mais les formats SSMS sont décimaux avec un point. Apparemment un problème connu .)

117
Andomar

Vous pouvez utiliser la fonction FORMAT() (SqlAzure et 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'

Faites attention lorsque vous utilisez FLOAT (ou REAL): n'utilisez pas g17 ou supérieur (ou g8 ou supérieur avec REAL), car la précision limitée de la représentation de la machine entraîne des effets indésirables:

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'

En outre, notez que, selon la documentation

FORMAT repose sur la présence du langage commun .NET Framework Durée d'exécution (CLR). Cette fonction ne sera pas retirée car elle dépend de la présence du CLR. Remoting une fonction qui nécessite le CLR provoquerait une erreur sur le serveur distant.

Fonctionne également dans SqlAzure.

26
robert4
SELECT CONVERT(DOUBLE PRECISION, [ColumnName])
11
Bat_Programmer
SELECT REVERSE(ROUND(REVERSE(2.5500),1))

impressions:

2.55
6
user1959416

J'étais réticent à l'idée de faire flotter à cause de la possibilité que plus de chiffres soient dans ma décimale que ce que flottant puisse représenter

FORMAT lorsque utilisé avec une chaîne de format .net standard 'g8' renvoyait la notation scientifique dans le cas de très petites décimales (par exemple 1e-08) qui était également inappropriée

L'utilisation d'une chaîne de format personnalisée ( https://docs.Microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings ) m'a permis de réaliser ce que je voulais:

DECLARE @n DECIMAL(9,6) =1.23;
SELECT @n
--> 1.230000
SELECT FORMAT(@n, '0.######')
--> 1.23

Si vous voulez que votre numéro ait au moins un zéro final, pour que 2.0 ne devienne pas 2, utilisez une chaîne de format telle que 0.0#####

La virgule décimale étant localisée, les cultures utilisant une virgule comme séparateur décimal se heurteront alors à une sortie par une virgule. est

Bien sûr, c’est la pratique décourageante d’avoir le formatage de la couche de données (mais dans mon cas, il n’existe aucune autre couche; l’utilisateur exécute littéralement une procédure stockée et met le résultat dans un courrier électronique: /)

5
Caius Jard

La meilleure solution consiste à NE PAS convertir enFLOATouMONEYavant la conversion en raison du risque de perte de précision. Ainsi, les moyens sécurisés peuvent être quelque chose comme ceci: 

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

où @value peut être any decimal (x, y)

2
Mahmoud Moravej
Cast(20.5500 as Decimal(6,2))

devrait le faire.

2
Peter Jones

J'avais un problème similaire, mais je devais également supprimer le point décimal lorsqu'aucune décimale n'était présente. Voici ma solution qui divise le point décimal en composants et fonde le nombre de caractères qu'il prend à partir de la chaîne de points le composant fraction (sans utiliser CASE). Pour rendre les choses encore plus intéressantes, mon numéro a été stocké sous forme de float sans décimales.

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

Le résultat est douloureux, je le sais, mais je suis arrivé là-bas, avec beaucoup d'aide des réponses ci-dessus.

2
Adge Cutler

J'ai eu un problème similaire, j'avais besoin de rogner des zéros à la fin d'un nombre tel que xx0000,x00000,xxx000

J'ai utilisé:

select LEFT(code,LEN(code)+1 - PATINDEX('%[1-Z]%',REVERSE(code))) from Tablename

Code est le nom du champ avec le numéro à couper. J'espère que ceci aide quelqu'un d'autre.

1
Kazeem Muritala

J'avais besoin de supprimer les zéros à la fin de mes décimales pour pouvoir sortir une chaîne d'une certaine longueur avec seulement de premier plan des zéros

(par exemple, je devais sortir 14 caractères pour que 142.023400 devienne 000000142.0234),

J'ai utilisé parsename, reverse et castas int pour supprimer les zéros de fin:

SELECT
    PARSENAME(2.5500,2)
    + '.'
    + REVERSE(CAST(REVERSE(PARSENAME(2.5500,1)) as int))

(Pour obtenir ensuite mes zéros de tête, je pourrais reproduire le nombre correct de zéros en fonction de la longueur de ce qui précède et concaténer ce texte au début de celui-ci.)

J'espère que cela aide quelqu'un.

1
Ali
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
0
beloblotskiy

Une autre option...

Je ne sais pas à quel point c'est efficace, mais cela semble fonctionner et ne passe pas par float:

select replace(rtrim(replace(
       replace(rtrim(replace(cast(@value as varchar(40)), '0', ' ')), ' ', '0')
       , '.', ' ')), ' ', '.')

La ligne du milieu supprime les espaces de fin, les deux autres suppriment le point s’il n’ya pas de chiffres décimaux

0
SQLian

il est possible de supprimer les zéros de début et de fin dans TSQL

  1. Convertissez-le en chaîne à l'aide de la fonction STR TSQL s'il ne s'agit pas d'une chaîne, alors 

  2. Supprimer les deux zéros en début et en fin

    SELECT REPLACE(RTRIM(LTRIM(REPLACE(AccNo,'0',' '))),' ','0') AccNo FROM @BankAccount
    
  3. Plus d'infos sur forum .

0
Ishtiaq

Que dis-tu de ça? En supposant que les données entrant dans votre fonction en tant que @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
0
MrNazgul

Je comprends que ceci est un ancien post, mais voudrais fournir SQL que je suis venu avec

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
0
Abhi

essaye ça.

select CAST(123.456700 as float),cast(cast(123.4567 as DECIMAL(9,6)) as float)
0
Vishal Kiri

Le moyen le plus simple consiste à CASTER la valeur en tant que FLOAT, puis en un type de données chaîne.

CAST(CAST(123.456000 AS FLOAT) AS VARCHAR(100))
0
Brad Raiche

Essaye ça : 

SELECT REPLACE(TRIM(REPLACE(20.5500, "0", " ")), " ", "0")

Donne 20.55

0
Todd