ฉันมีคอลัมน์DECIMAL(9,6)
คือรองรับค่าเช่น 999,123456
แต่เมื่อฉันแทรกข้อมูลเช่น 123,4567 มันจะกลายเป็น 123,456700
จะลบเลขศูนย์เหล่านั้นได้อย่างไร?
ฉันมีคอลัมน์DECIMAL(9,6)
คือรองรับค่าเช่น 999,123456
แต่เมื่อฉันแทรกข้อมูลเช่น 123,4567 มันจะกลายเป็น 123,456700
จะลบเลขศูนย์เหล่านั้นได้อย่างไร?
คำตอบ:
decimal(9,6)
ร้านค้า 6 หลักที่ด้านขวาของเครื่องหมายจุลภาค การแสดงค่าศูนย์ต่อท้ายหรือไม่เป็นการตัดสินใจในการจัดรูปแบบซึ่งโดยปกติจะใช้กับฝั่งไคลเอ็นต์
แต่เนื่องจากรูปแบบ SSMS ที่float
ไม่มีศูนย์ต่อท้ายคุณสามารถลบศูนย์ต่อท้ายได้โดยการส่งdecimal
ไปยัง a float
:
select
cast(123.4567 as DECIMAL(9,6))
, cast(cast(123.4567 as DECIMAL(9,6)) as float)
พิมพ์:
123.456700 123,4567
(ตัวคั่นทศนิยมของฉันเป็นลูกน้ำ แต่ SSMS จัดรูปแบบทศนิยมด้วยจุดเห็นได้ชัดว่าเป็นปัญหาที่ทราบ)
คุณสามารถใช้FORMAT()
ฟังก์ชัน (SqlAzure และ 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 (หรือ REAL): อย่าใช้g17
หรือใหญ่กว่า ( g8
หรือใหญ่กว่าด้วย REAL) เนื่องจากความแม่นยำที่ จำกัด ของการแสดงเครื่องทำให้เกิดผลกระทบที่ไม่ต้องการ:
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'
นอกจากนี้โปรดทราบว่าตามเอกสารประกอบ :
FORMAT อาศัยการมีอยู่ของ. NET Framework Common Language Runtime (CLR) ฟังก์ชันนี้จะไม่ถูกรีบูตเนื่องจากขึ้นอยู่กับการมีอยู่ของ CLR การรีบูตฟังก์ชันที่ต้องใช้ CLR อาจทำให้เกิดข้อผิดพลาดบนเซิร์ฟเวอร์ระยะไกล
ทำงานใน SqlAzure ได้เช่นกัน
SELECT CONVERT(DOUBLE PRECISION, [ColumnName])
ฉันลังเลที่จะโยนให้ลอยเพราะมีโอกาสที่ตัวเลขจะอยู่ในทศนิยมมากกว่าที่ทศนิยมจะแสดงได้
FORMAT
เมื่อใช้กับสตริงรูปแบบ. net 'g8' จะส่งคืนสัญกรณ์ทางวิทยาศาสตร์ในกรณีของทศนิยมที่มีขนาดเล็กมาก (เช่น 1e-08) ซึ่งไม่เหมาะสมเช่นกัน
การใช้สตริงรูปแบบที่กำหนดเอง ( https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings ) ทำให้ฉันบรรลุสิ่งที่ต้องการ:
DECLARE @n DECIMAL(9,6) =1.23;
SELECT @n
--> 1.230000
SELECT FORMAT(@n, '0.######')
--> 1.23
หากคุณต้องการให้ตัวเลขของคุณมีศูนย์ต่อท้ายอย่างน้อยหนึ่งตัวดังนั้น 2.0 จึงไม่กลายเป็น 2 ให้ใช้สตริงรูปแบบเช่น 0.0#####
จุดทศนิยมถูกแปลเป็นภาษาท้องถิ่นดังนั้นวัฒนธรรมที่ใช้ลูกน้ำเป็นตัวคั่นทศนิยมจะพบกับเอาต์พุตลูกน้ำโดยที่. คือ
แน่นอนว่านี่เป็นวิธีปฏิบัติที่น่าท้อใจในการให้ชั้นข้อมูลทำการจัดรูปแบบ (แต่ในกรณีของฉันไม่มีเลเยอร์อื่นผู้ใช้กำลังเรียกใช้ขั้นตอนการจัดเก็บอย่างแท้จริงและวางผลลัพธ์ในอีเมล: /)
SELECT REVERSE(ROUND(REVERSE(2.5500),1))
พิมพ์:
2.55
Cast(20.5500 as Decimal(6,2))
ควรทำ
ลองสิ่งนี้:
SELECT REPLACE(TRIM(REPLACE(20.5500, "0", " ")), " ", "0")
ให้ 20.55
0.000
.
นี่คือการแก้ไขSELECT REPLACE(RTRIM(REPLACE(20.5500, "0", " ")), " ", "0")
เพื่อตัดค่าศูนย์ต่อท้ายเท่านั้น
ฉันมีปัญหาที่คล้ายกัน แต่ก็จำเป็นต้องลบจุดทศนิยมที่ไม่มีจุดทศนิยมนี่คือวิธีแก้ปัญหาของฉันซึ่งแบ่งทศนิยมออกเป็นส่วนประกอบและฐานจำนวนอักขระที่ใช้จากสตริงจุดทศนิยมตามความยาวของ ส่วนประกอบเศษส่วน (โดยไม่ใช้ CASE) เพื่อให้เรื่องน่าสนใจยิ่งขึ้นจำนวนของฉันถูกจัดเก็บเป็นทศนิยมโดยไม่มีทศนิยม
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')
ผลลัพธ์นั้นเจ็บปวดฉันรู้ แต่ฉันไปถึงที่นั่นด้วยความช่วยเหลือมากมายจากคำตอบข้างต้น
วิธีที่ดีที่สุดคืออย่าแปลงเป็นFLOATหรือMONEYก่อนที่จะแปลงเนื่องจากมีโอกาสสูญเสียความแม่นยำ ดังนั้นวิธีที่ปลอดภัยอาจเป็นดังนี้:
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 สามารถใด ๆทศนิยม (x, y)
sp_
สำหรับขั้นตอนการจัดเก็บfn_
สำหรับฟังก์ชันtbl
สำหรับตารางและอื่น ๆ บน ... นี่ไม่ใช่ข้อกำหนด แต่เป็นแนวทางปฏิบัติที่ดีที่สุดในการจัดระเบียบฐานข้อมูลของเรา
ฉันมีปัญหาที่คล้ายกันจำเป็นต้องตัดเลขศูนย์ต่อท้ายจากตัวเลขเช่น xx0000,x00000,xxx000
ฉันใช้:
select LEFT(code,LEN(code)+1 - PATINDEX('%[1-Z]%',REVERSE(code))) from Tablename
รหัสคือชื่อของเขตข้อมูลที่มีหมายเลขที่จะตัดแต่ง หวังว่านี่จะช่วยคนอื่นได้
อีกทางเลือกหนึ่ง ...
ฉันไม่รู้ว่ามันมีประสิทธิภาพแค่ไหน แต่ดูเหมือนว่าจะใช้งานได้และไม่ผ่าน float:
select replace(rtrim(replace(
replace(rtrim(replace(cast(@value as varchar(40)), '0', ' ')), ' ', '0')
, '.', ' ')), ' ', '.')
เส้นกลางจะตัดช่องว่างต่อท้ายสองจุดด้านนอกจะลบจุดหากไม่มีตัวเลขทศนิยม
ฉันต้องการลบเลขศูนย์ต่อท้ายบนทศนิยมของฉันเพื่อที่ฉันจะได้เอาท์พุทสตริงที่มีความยาวหนึ่งโดยมีเฉพาะนำหน้าเท่านั้นเลขศูนย์หน้า
(เช่นฉันต้องการเอาต์พุต 14 ตัวอักษรดังนั้น 142.023400 จะกลายเป็น 000000142.0234)
ผมใช้parsename
, reverse
และcast
as int
เพื่อลบเลขศูนย์ต่อท้าย:
SELECT
PARSENAME(2.5500,2)
+ '.'
+ REVERSE(CAST(REVERSE(PARSENAME(2.5500,1)) as int))
(เพื่อให้ได้ศูนย์นำหน้าของฉันฉันสามารถจำลองจำนวนศูนย์ที่ถูกต้องตามความยาวของด้านบนและเชื่อมสิ่งนี้เข้ากับด้านหน้าของด้านบน)
ฉันหวังว่านี่จะช่วยใครสักคน
REPLACE(RTRIM(REPLACE(REPLACE(RTRIM(REPLACE(X,'0',' ')),' ','0'),'.',' ')),' ','.')
แล้วเรื่องนี้ล่ะ? สมมติว่าข้อมูลเข้ามาในฟังก์ชันของคุณเป็น @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
ฉันเข้าใจว่านี่เป็นโพสต์เก่า แต่ต้องการให้ SQL ที่ฉันสร้างขึ้นมา
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
ลองดู
select CAST(123.456700 as float),cast(cast(123.4567 as DECIMAL(9,6)) as float)
วิธีที่ง่ายที่สุดคือแคสต์ค่าเป็น FLOAT จากนั้นไปยังประเภทข้อมูลสตริง
CAST(CAST(123.456000 AS FLOAT) AS VARCHAR(100))
ลองสิ่งนี้:
select Cast( Cast( (ROUND( 35.457514 , 2) *100) as Int) as float ) /100
ฉันรู้ว่าเธรดนี้เก่ามาก แต่สำหรับผู้ที่ไม่ได้ใช้ SQL Server 2012 ขึ้นไปหรือไม่สามารถใช้ฟังก์ชัน FORMAT ไม่ว่าด้วยเหตุผลใดก็ตามต่อไปนี้จะใช้งานได้
นอกจากนี้วิธีแก้ปัญหาจำนวนมากไม่ทำงานหากตัวเลขน้อยกว่า 1 (เช่น 0.01230000)
โปรดทราบว่าสิ่งต่อไปนี้ใช้ไม่ได้กับตัวเลขติดลบ
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')
ส่งกลับ 10.012345 และ 0.012345 ตามลำดับ
ลองสิ่งนี้:
select isnull(cast(floor(replace(rtrim(ltrim('999,999.0000')),',','')) as int),0)
999999
OP ขอให้ลบเลขศูนย์ต่อท้าย
คอลัมน์ DECIMAL (9,6) จะแปลงเป็น float โดยไม่สูญเสียความแม่นยำดังนั้น CAST (... AS float) จะทำเคล็ดลับ
@HLGEM: การบอกว่าลูกลอยเป็นตัวเลือกที่ไม่ดีสำหรับการจัดเก็บตัวเลขและ "ห้ามใช้ลูกลอย" นั้นไม่ถูกต้อง - คุณเพียงแค่ต้องรู้ตัวเลขของคุณเช่นการวัดอุณหภูมิจะไปได้ดีเหมือนกับการลอย
@abatishchev และ @japongskie: คำนำหน้าอยู่หน้า procs และฟังก์ชันที่จัดเก็บ SQL ยังคงเป็นความคิดที่ดีหากไม่จำเป็น ลิงก์ที่คุณกล่าวถึงเพียงสั่งให้ไม่ใช้คำนำหน้า "sp_" สำหรับโพรซีเดอร์ที่เก็บไว้ซึ่งคุณไม่ควรใช้คำนำหน้าอื่น ๆ ก็ใช้ได้เช่น "usp_" หรือ "spBob_"
ข้อมูลอ้างอิง: "จำนวนเต็มทั้งหมดที่มีตัวเลขทศนิยมที่มีนัยสำคัญ 6 หลักหรือน้อยกว่าสามารถแปลงเป็นค่าทศนิยม IEEE 754 ได้โดยไม่สูญเสียความแม่นยำ": https://en.wikipedia.org/wiki/Single-precision_floating-point_format