Bir DECIMAL(9,6)
sütunum var yani 999,123456 gibi değerleri destekliyor.
Ama 123.4567 gibi bir veri eklediğimde 123.456700 oluyor
Bu sıfırlar nasıl kaldırılır?
Bir DECIMAL(9,6)
sütunum var yani 999,123456 gibi değerleri destekliyor.
Ama 123.4567 gibi bir veri eklediğimde 123.456700 oluyor
Bu sıfırlar nasıl kaldırılır?
Yanıtlar:
A decimal(9,6)
, virgülün sağ tarafında 6 basamak saklar. Sondaki sıfırların gösterilip gösterilmeyeceği, genellikle istemci tarafında uygulanan bir biçimlendirme kararıdır.
Ama ssms formatları beri float
sondaki sıfırlar olmadan, sen döküm yoluyla sıfır sondaki kaldırabilirsiniz decimal
a float
:
select
cast(123.4567 as DECIMAL(9,6))
, cast(cast(123.4567 as DECIMAL(9,6)) as float)
baskılar:
123.456700 123,4567
(Ondalık ayırıcım virgülden oluşuyor, ancak SSMS ondalık noktayı bir noktayla biçimlendiriyor. Görünüşe göre bilinen bir sorun .)
FORMAT()
İşlevi kullanabilirsiniz (SqlAzure ve 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'
FLOAT (veya GERÇEK) ile kullanırken dikkatli olun: g17
veya daha büyük (veya g8
REAL ile daha büyük) kullanmayın, çünkü makine temsilinin sınırlı hassasiyeti istenmeyen etkilere neden olur:
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'
Ayrıca, belgelere göre şunları unutmayın :
FORMAT, .NET Framework Ortak Dil Çalışma Zamanı'nın (CLR) varlığına dayanır. CLR'nin varlığına bağlı olduğu için bu işlev uzaktan kumanda edilmeyecektir. CLR gerektiren bir işlevi yeniden başlatmak, uzak sunucuda bir hataya neden olur.
SqlAzure'de de çalışıyor.
SELECT CONVERT(DOUBLE PRECISION, [ColumnName])
Float'ın temsil edebileceğinden daha fazla rakamın ondalık dilimde olma potansiyeli nedeniyle float'a dönüştürme konusunda isteksizdim
FORMAT
standart .net formatlı bir dizeyle kullanıldığında 'g8', çok küçük ondalık sayılarda (örn. 1e-08) bilimsel gösterimi döndürdü ve bu da uygun değildi
Özel bir biçim dizesi kullanmak ( https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings ) istediğim şeyi elde etmemi sağladı:
DECLARE @n DECIMAL(9,6) =1.23;
SELECT @n
--> 1.230000
SELECT FORMAT(@n, '0.######')
--> 1.23
Numaranızın sonunda en az bir sıfır olmasını istiyorsanız, böylece 2.0 2 olmaz, aşağıdaki gibi bir biçim dizesi kullanın 0.0#####
Ondalık nokta yerelleştirilmiştir, bu nedenle ondalık ayırıcı olarak virgül kullanan kültürler,. dır-dir
Elbette bu, veri katmanının biçimlendirme yapmasının tavsiye edilemeyecek bir uygulamasıdır (ancak benim durumumda başka bir katman yoktur; kullanıcı tam anlamıyla bir saklı yordamı çalıştırıyor ve sonucu bir e-postaya koyuyor: /)
SELECT REVERSE(ROUND(REVERSE(2.5500),1))
baskılar:
2.55
Cast(20.5500 as Decimal(6,2))
yapmalı.
Bunu dene :
SELECT REPLACE(TRIM(REPLACE(20.5500, "0", " ")), " ", "0")
20,55 verir
0.000
oldu .
. işte SELECT REPLACE(RTRIM(REPLACE(20.5500, "0", " ")), " ", "0")
sadece sondaki sıfırları kırpmak için düzeltme
Benzer bir sorunum vardı, ancak ondalık basamağın bulunmadığı ondalık noktayı da kaldırmam gerekiyordu, işte ondalık sayıları bileşenlerine bölen ve ondalık nokta dizesinden aldığı karakterlerin uzunluğunu temel alan çözümüm buydu. kesir bileşeni (CASE kullanmadan). Konuları daha da ilginç kılmak için, numaram ondalık sayıları olmadan bir kayan nokta olarak saklandı.
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')
Sonuç acı verici, biliyorum, ama oraya yukarıdaki cevapların çok yardımıyla ulaştım.
En iyi yol, kesinlik kaybı ihtimali nedeniyle dönüştürmeden önce FLOAT veya PARA'ya dönüştürmemektir. Dolayısıyla güvenli yollar şunun gibi bir şey olabilir:
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
@value herhangi bir ondalık (x, y) olabilir
sp_
için saklı yordam, fn_
işlevler, tbl
tablolar vb. üzerinde ... bu bir gereklilik değildir, ancak bu, veritabanımızı düzenlemek için en iyi uygulamalardır.
Benzer bir sorun yaşadım, sondaki sıfırları aşağıdaki gibi sayılardan kırpmam gerekiyordu. xx0000,x00000,xxx000
Kullandım:
select LEFT(code,LEN(code)+1 - PATINDEX('%[1-Z]%',REVERSE(code))) from Tablename
Kod, kırpılacak numaranın bulunduğu alanın adıdır. Umarım bu başka birine yardımcı olur.
Başka seçenek...
Bunun ne kadar verimli olduğunu bilmiyorum ama işe yarıyor gibi görünüyor ve float ile gitmiyor:
select replace(rtrim(replace(
replace(rtrim(replace(cast(@value as varchar(40)), '0', ' ')), ' ', '0')
, '.', ' ')), ' ', '.')
Orta çizgi sondaki boşlukları çıkarır, dıştaki iki ondalık basamak yoksa noktayı kaldırır
Ondalık sayılarımın sonundaki sıfırları kaldırmam gerekiyordu, böylece yalnızca önde gelen belirli bir uzunlukta bir dize çıkarabilirdim sıfırlar
(örneğin 142.023400'ün 000000142.0234 olması için 14 karakter çıktı vermem gerekiyordu),
Kullandığım parsename
, reverse
ve cast
as int
arka sıfır kaldırmak:
SELECT
PARSENAME(2.5500,2)
+ '.'
+ REVERSE(CAST(REVERSE(PARSENAME(2.5500,1)) as int))
(Daha sonra baştaki sıfırlarımı elde etmek için, yukarıdakilerin uzunluğuna göre doğru sayıda sıfırları çoğaltabilir ve bunu yukarıdakinin önüne birleştirebilirim)
Umarım bu birine yardımcı olur.
TSQL'de baştaki ve sondaki sıfırları kaldırmak mümkündür
Dize değilse STR TSQL işlevini kullanarak dizgeye dönüştürün, Sonra
Baştaki ve sondaki sıfırları kaldırın
SELECT REPLACE(RTRIM(LTRIM(REPLACE(AccNo,'0',' '))),' ','0') AccNo FROM @BankAccount
Forum hakkında daha fazla bilgi .
REPLACE(RTRIM(REPLACE(REPLACE(RTRIM(REPLACE(X,'0',' ')),' ','0'),'.',' ')),' ','.')
Buna ne dersin? İşlevinize @thisData olarak gelen verileri varsayarsak:
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
Bunun eski bir gönderi olduğunu anlıyorum ancak bulduğum SQL'i sağlamak istiyorum
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
bunu dene.
select CAST(123.456700 as float),cast(cast(123.4567 as DECIMAL(9,6)) as float)
En kolay yol, değeri FLOAT olarak ve ardından bir dize veri türü olarak CAST yapmaktır.
CAST(CAST(123.456000 AS FLOAT) AS VARCHAR(100))
Bunu dene:
select Cast( Cast( (ROUND( 35.457514 , 2) *100) as Int) as float ) /100
Bu iş parçacığının çok eski olduğunu biliyorum ancak SQL Server 2012 veya üzeri kullanmayanlar veya herhangi bir nedenle FORMAT işlevini kullanamayanlar için aşağıdakiler çalışıyor.
Ayrıca, sayı 1'den küçükse çözümlerin çoğu işe yaramadı (ör. 0,01230000).
Lütfen aşağıdakilerin negatif sayılarla çalışmadığını unutmayın.
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')
Sırasıyla 10.012345 ve 0.012345 döndürür.
Bunu dene:
select isnull(cast(floor(replace(rtrim(ltrim('999,999.0000')),',','')) as int),0)
999999
, OP sondaki sıfırları kaldırmayı ister.
Ondalık (9,6) sütunu, hassasiyet kaybı olmaksızın kayan noktaya dönüşür, bu nedenle CAST (... AS float) hile yapar.
@HLGEM: Float'ın sayıları saklamak için kötü bir seçim olduğunu ve "Asla float kullanmayın" demek doğru değildir - sadece sayılarınızı bilmeniz gerekir, örneğin sıcaklık ölçümleri float gibi iyi gider.
@abatishchev ve @japongskie: SQL'de depolanan işlemlerin ve işlevlerin önündeki ön ekler, gerekmiyorsa yine de iyi bir fikirdir; Bahsettiğiniz bağlantılar, kullanmamanız gereken saklı yordamlar için yalnızca "sp_" önekini kullanmama talimatı verir, diğer önekler uygundur, örneğin "usp_" veya "spBob_"
Referans: "6 veya daha az ondalık basamağa sahip tüm tamsayılar, hassasiyet kaybı olmadan IEEE 754 kayan noktalı değere dönüştürülebilir": https://en.wikipedia.org/wiki/Single-precision_floating-point_format