Ho una colonna, DECIMAL(9,6)
ovvero supporta valori come 999,123456.
Ma quando inserisco dati come 123,4567 diventa 123,456700
Come rimuovere quegli zeri?
Ho una colonna, DECIMAL(9,6)
ovvero supporta valori come 999,123456.
Ma quando inserisco dati come 123,4567 diventa 123,456700
Come rimuovere quegli zeri?
Risposte:
A decimal(9,6)
memorizza 6 cifre a destra della virgola. Se visualizzare o meno gli zeri finali è una decisione di formattazione, solitamente implementata dal lato client.
Ma poiché SSMS formatta float
senza zeri finali, è possibile rimuovere gli zeri finali eseguendo il cast decimal
di a float
:
select
cast(123.4567 as DECIMAL(9,6))
, cast(cast(123.4567 as DECIMAL(9,6)) as float)
stampe:
123.456700 123,4567
(Il mio separatore decimale è una virgola, ma SSMS formatta il decimale con un punto. Apparentemente un problema noto .)
È possibile utilizzare la FORMAT()
funzione (SqlAzure e 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'
Fare attenzione quando si utilizza con FLOAT (o REAL): non utilizzare g17
o maggiore (o g8
o maggiore con REAL), perché la limitata precisione della rappresentazione della macchina provoca effetti indesiderati:
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'
Si noti inoltre che, secondo la documentazione :
FORMAT si basa sulla presenza di .NET Framework Common Language Runtime (CLR). Questa funzione non verrà remotata poiché dipende dalla presenza del CLR. Il remotaggio di una funzione che richiede CLR provocherebbe un errore sul server remoto.
Funziona anche in SqlAzure.
SELECT CONVERT(DOUBLE PRECISION, [ColumnName])
Ero riluttante a lanciare in float a causa della possibilità che più cifre siano nel mio decimale di quanto il float possa rappresentare
FORMAT
se usato con una stringa di formato .net standard 'g8' restituiva la notazione scientifica in casi di decimali molto piccoli (es. 1e-08) che era anche inadatta
L'utilizzo di una stringa di formato personalizzata ( https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings ) mi ha permesso di ottenere ciò che volevo:
DECLARE @n DECIMAL(9,6) =1.23;
SELECT @n
--> 1.230000
SELECT FORMAT(@n, '0.######')
--> 1.23
Se vuoi che il tuo numero abbia almeno uno zero finale, quindi 2.0 non diventa 2, usa una stringa di formato come 0.0#####
Il punto decimale è localizzato, quindi le culture che usano una virgola come separatore decimale incontreranno un output di virgola in cui il. è
Naturalmente, questa è la pratica scoraggiante di avere il livello dati che esegue la formattazione (ma nel mio caso non c'è nessun altro livello; l'utente sta letteralmente eseguendo una procedura memorizzata e inserendo il risultato in un'e-mail: /)
SELECT REVERSE(ROUND(REVERSE(2.5500),1))
stampe:
2.55
Cast(20.5500 as Decimal(6,2))
dovrebbe farlo.
Prova questo :
SELECT REPLACE(TRIM(REPLACE(20.5500, "0", " ")), " ", "0")
Dà 20,55
0.000
diventato .
. ecco la correzione SELECT REPLACE(RTRIM(REPLACE(20.5500, "0", " ")), " ", "0")
per tagliare solo gli zeri finali
Ho avuto un problema simile, ma è stato anche richiesto di rimuovere il punto decimale dove non era presente alcun decimale, ecco la mia soluzione che divide il decimale nei suoi componenti e basa il numero di caratteri che prende dalla stringa del punto decimale sulla lunghezza di il componente frazione (senza utilizzare CASE). Per rendere le cose ancora più interessanti, il mio numero è stato memorizzato come un galleggiante senza i suoi decimali.
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')
Il risultato è doloroso, lo so, ma ci sono arrivato, con molto aiuto dalle risposte sopra.
Il modo migliore è NON convertire in FLOAT o MONEY prima della conversione a causa della possibilità di perdita di precisione. Quindi i modi sicuri possono essere qualcosa del genere:
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
dove @value può essere qualsiasi decimale (x, y)
sp_
per le procedure memorizzate, fn_
per le funzioni, tbl
per le tabelle e così via su ... questo non è un requisito ma questa è la migliore pratica per organizzare i nostri database.
Ho avuto un problema simile, dovevo tagliare gli zeri finali da numeri come xx0000,x00000,xxx000
Ero solito:
select LEFT(code,LEN(code)+1 - PATINDEX('%[1-Z]%',REVERSE(code))) from Tablename
Codice è il nome del campo con il numero da tagliare. Spero che questo aiuti qualcun altro.
Un'altra opzione...
Non so quanto sia efficiente ma sembra funzionare e non funziona tramite float:
select replace(rtrim(replace(
replace(rtrim(replace(cast(@value as varchar(40)), '0', ' ')), ' ', '0')
, '.', ' ')), ' ', '.')
La linea centrale rimuove gli spazi finali, i due esterni rimuovono il punto se non ci sono cifre decimali
Ho bisogno di rimuovere zeri sui miei decimali trascinamento così ho potuto uscita una stringa di una determinata lunghezza con solo leader zeri
(es. dovevo produrre 14 caratteri in modo che 142.023400 diventasse 000000142.0234),
Ho usato parsename
, reverse
e cast
as int
per rimuovere gli zeri:
SELECT
PARSENAME(2.5500,2)
+ '.'
+ REVERSE(CAST(REVERSE(PARSENAME(2.5500,1)) as int))
(Per ottenere i miei zeri iniziali potrei replicare il numero corretto di zeri in base alla lunghezza di quanto sopra e concatenarlo davanti a quanto sopra)
Spero che questo aiuti qualcuno.
è possibile rimuovere gli zeri iniziali e finali in TSQL
Convertirlo in stringa utilizzando la funzione STR TSQL se non stringa, quindi
Rimuovi entrambi gli zeri iniziali e finali
SELECT REPLACE(RTRIM(LTRIM(REPLACE(AccNo,'0',' '))),' ','0') AccNo FROM @BankAccount
Maggiori informazioni sul forum .
REPLACE(RTRIM(REPLACE(REPLACE(RTRIM(REPLACE(X,'0',' ')),' ','0'),'.',' ')),' ','.')
Cosa ne pensi di questo? Supponendo che i dati entrino nella tua funzione come @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
Capisco che questo sia un vecchio post, ma vorrei fornire SQL che mi è venuto in mente
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
prova questo.
select CAST(123.456700 as float),cast(cast(123.4567 as DECIMAL(9,6)) as float)
Il modo più semplice consiste nel CAST il valore come FLOAT e quindi in un tipo di dati stringa.
CAST(CAST(123.456000 AS FLOAT) AS VARCHAR(100))
Prova questo:
select Cast( Cast( (ROUND( 35.457514 , 2) *100) as Int) as float ) /100
So che questo thread è molto vecchio ma per coloro che non utilizzano SQL Server 2012 o versioni successive o non possono utilizzare la funzione FORMAT per qualsiasi motivo, il seguente funziona.
Inoltre, molte soluzioni non funzionavano se il numero era inferiore a 1 (ad es. 0,01230000).
Tieni presente che quanto segue non funziona con i numeri negativi.
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')
Restituisce rispettivamente 10,012345 e 0,012345.
Prova questo:
select isnull(cast(floor(replace(rtrim(ltrim('999,999.0000')),',','')) as int),0)
999999
, l'OP chiede di rimuovere gli zeri finali.
Una colonna DECIMAL (9,6) verrà convertita in float senza perdita di precisione, quindi CAST (... AS float) farà il trucco.
@HLGEM: dire che il float è una scelta sbagliata per memorizzare i numeri e "Non usare mai il float" non è corretto - devi solo conoscere i tuoi numeri, ad esempio le misurazioni della temperatura andrebbero bene come galleggianti.
@abatishchev e @japongskie: i prefissi davanti alle procedure e alle funzioni archiviate in SQL sono ancora una buona idea, se non richieste; i collegamenti che hai menzionato indicano solo di non utilizzare il prefisso "sp_" per le procedure memorizzate che non dovresti usare, altri prefissi vanno bene ad esempio "usp_" o "spBob_"
Riferimento: "Tutti i numeri interi con 6 o meno cifre decimali significative possono essere convertiti in un valore a virgola mobile IEEE 754 senza perdita di precisione": https://en.wikipedia.org/wiki/Single-precision_floating-point_format