Tôi có một cột DECIMAL(9,6)
tức là nó hỗ trợ các giá trị như 999,123456.
Nhưng khi tôi chèn dữ liệu như 123,4567, nó sẽ trở thành 123,456700
Làm thế nào để loại bỏ những số không?
Tôi có một cột DECIMAL(9,6)
tức là nó hỗ trợ các giá trị như 999,123456.
Nhưng khi tôi chèn dữ liệu như 123,4567, nó sẽ trở thành 123,456700
Làm thế nào để loại bỏ những số không?
Câu trả lời:
A decimal(9,6)
lưu 6 chữ số bên phải dấu phẩy. Việc có hiển thị các số 0 ở cuối hay không là một quyết định định dạng, thường được thực hiện ở phía máy khách.
Nhưng vì các định dạng SSMS float
không có số 0 ở cuối, bạn có thể xóa các số 0 ở cuối bằng cách decimal
chuyển thành float
:
select
cast(123.4567 as DECIMAL(9,6))
, cast(cast(123.4567 as DECIMAL(9,6)) as float)
bản in:
123.456700 123,4567
(Dấu phân tách thập phân của tôi là dấu phẩy, nhưng SSMS định dạng thập phân với dấu chấm. Rõ ràng là một vấn đề đã biết .)
Bạn có thể sử dụng FORMAT()
chức năng (SqlAzure và 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'
Cẩn thận khi sử dụng với FLOAT (hoặc REAL): không sử dụng g17
hoặc lớn hơn ( g8
hoặc lớn hơn với REAL), vì độ chính xác hạn chế của biểu diễn máy gây ra các tác dụng không mong muốn:
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'
Hơn nữa, hãy lưu ý rằng, theo tài liệu :
FORMAT dựa trên sự hiện diện của .NET Framework Common Language Runtime (CLR). Chức năng này sẽ không được khởi động lại vì nó phụ thuộc vào sự hiện diện của CLR. Việc khởi động lại một chức năng yêu cầu CLR sẽ gây ra lỗi trên máy chủ từ xa.
Cũng hoạt động trong SqlAzure.
SELECT CONVERT(DOUBLE PRECISION, [ColumnName])
Tôi đã miễn cưỡng chuyển sang float vì khả năng có nhiều chữ số trong số thập phân của tôi hơn số float có thể đại diện
FORMAT
khi được sử dụng với chuỗi định dạng .net tiêu chuẩn 'g8' trả về ký hiệu khoa học trong các trường hợp số thập phân rất nhỏ (ví dụ: 1e-08) cũng không phù hợp
Sử dụng chuỗi định dạng tùy chỉnh ( https://docs.microsoft.com/en-us/dotnet/standard/base-types/custom-numeric-format-strings ) cho phép tôi đạt được những gì tôi muốn:
DECLARE @n DECIMAL(9,6) =1.23;
SELECT @n
--> 1.230000
SELECT FORMAT(@n, '0.######')
--> 1.23
Nếu bạn muốn số của mình có ít nhất một số 0 ở cuối, vì vậy 2.0 không trở thành 2, hãy sử dụng chuỗi định dạng như 0.0#####
Dấu thập phân được bản địa hóa, vì vậy các nền văn hóa sử dụng dấu phẩy làm dấu phân tách thập phân sẽ gặp phải đầu ra dấu phẩy trong đó. Là
Tất nhiên, đây là thực tế không khuyến khích khi để lớp dữ liệu thực hiện định dạng (nhưng trong trường hợp của tôi thì không có lớp nào khác; người dùng thực sự đang chạy một thủ tục được lưu trữ và đưa kết quả vào email: /)
SELECT REVERSE(ROUND(REVERSE(2.5500),1))
bản in:
2.55
Cast(20.5500 as Decimal(6,2))
Hãy làm nó.
Thử đi :
SELECT REPLACE(TRIM(REPLACE(20.5500, "0", " ")), " ", "0")
Cho 20,55
0.000
đã trở thành .
. đây là bản sửa lỗi SELECT REPLACE(RTRIM(REPLACE(20.5500, "0", " ")), " ", "0")
để chỉ cắt các số không ở cuối
Tôi đã gặp sự cố tương tự nhưng cũng được yêu cầu xóa dấu thập phân nơi không có số thập phân, đây là giải pháp của tôi chia số thập phân thành các thành phần của nó và căn cứ vào số ký tự mà nó lấy từ chuỗi dấu thập phân trên độ dài của thành phần phân số (không sử dụng CASE). Để làm cho vấn đề thú vị hơn nữa, số của tôi đã được lưu trữ dưới dạng một phao không có số thập phân.
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')
Kết quả là đau đớn, tôi biết, nhưng tôi đã đạt được điều đó, với sự trợ giúp rất nhiều từ những câu trả lời ở trên.
Cách tốt nhất là KHÔNG chuyển đổi sang FLOAT hoặc MONEY trước khi chuyển đổi vì có thể mất độ chính xác. Vì vậy, các cách an toàn có thể giống như sau:
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
trong đó @value có thể là bất kỳ số thập phân nào (x, y)
sp_
cho thủ tục lưu trữ, fn_
cho các chức năng, tbl
cho các bảng và do đó về ... đây không phải là một yêu cầu nhưng đây là phương pháp hay nhất để tổ chức cơ sở dữ liệu của chúng tôi.
Tôi đã gặp sự cố tương tự, cần phải cắt các số không ở cuối khỏi các số như xx0000,x00000,xxx000
Tôi đã sử dụng:
select LEFT(code,LEN(code)+1 - PATINDEX('%[1-Z]%',REVERSE(code))) from Tablename
Mã là tên của trường có số được cắt bớt. Hy vọng điều này sẽ giúp người khác.
Một lựa chọn khác ...
Tôi không biết điều này hiệu quả như thế nào nhưng nó có vẻ hoạt động và không đi qua float:
select replace(rtrim(replace(
replace(rtrim(replace(cast(@value as varchar(40)), '0', ' ')), ' ', '0')
, '.', ' ')), ' ', '.')
Dòng giữa loại bỏ dấu cách ở cuối, hai dòng ngoài xóa dấu chấm nếu không có chữ số thập phân
Tôi cần xóa các số không ở cuối trên số thập phân của mình để tôi có thể xuất một chuỗi có độ dài nhất định chỉ với các số 0 ở đầu
(ví dụ: tôi cần xuất ra 14 ký tự để 142.023400 sẽ trở thành 000000142.0234),
Tôi đã sử dụng parsename
, reverse
và cast
as int
để loại bỏ các số không dấu:
SELECT
PARSENAME(2.5500,2)
+ '.'
+ REVERSE(CAST(REVERSE(PARSENAME(2.5500,1)) as int))
(Để có được các số 0 ở đầu của tôi, tôi có thể sao chép đúng số lượng các số không dựa trên độ dài của số trên và nối số này với phía trước của số trên)
Tôi hi vọng nó sẽ giúp ích cho mọi người.
có thể loại bỏ các số không ở đầu và cuối trong TSQL
Chuyển nó thành chuỗi bằng cách sử dụng hàm STR TSQL nếu không phải là chuỗi, Sau đó
Xóa cả số không ở đầu và ở cuối
SELECT REPLACE(RTRIM(LTRIM(REPLACE(AccNo,'0',' '))),' ','0') AccNo FROM @BankAccount
Thêm thông tin trên diễn đàn .
REPLACE(RTRIM(REPLACE(REPLACE(RTRIM(REPLACE(X,'0',' ')),' ','0'),'.',' ')),' ','.')
Còn cái này thì sao? Giả sử dữ liệu đi vào chức năng của bạn dưới dạng @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
Tôi hiểu đây là một bài đăng cũ nhưng tôi muốn cung cấp SQL mà tôi đã nghĩ ra
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
thử đi.
select CAST(123.456700 as float),cast(cast(123.4567 as DECIMAL(9,6)) as float)
Cách dễ nhất là CAST giá trị dưới dạng FLOAT và sau đó là kiểu dữ liệu chuỗi.
CAST(CAST(123.456000 AS FLOAT) AS VARCHAR(100))
Thử đi:
select Cast( Cast( (ROUND( 35.457514 , 2) *100) as Int) as float ) /100
Tôi biết chủ đề này rất cũ nhưng đối với những người không sử dụng SQL Server 2012 trở lên hoặc không thể sử dụng chức năng FORMAT vì bất kỳ lý do nào thì những điều sau sẽ hoạt động.
Ngoài ra, rất nhiều giải pháp không hoạt động nếu số nhỏ hơn 1 (ví dụ: 0,01230000).
Xin lưu ý rằng điều sau đây không hoạt động với số âm.
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')
Trả về lần lượt là 10,012345 và 0,012345.
Thử đi:
select isnull(cast(floor(replace(rtrim(ltrim('999,999.0000')),',','')) as int),0)
999999
, OP yêu cầu loại bỏ các số không ở cuối.
Cột DECIMAL (9,6) sẽ chuyển thành float mà không làm mất độ chính xác, vì vậy CAST (... AS float) sẽ thực hiện thủ thuật.
@HLGEM: nói rằng float là một lựa chọn tồi để lưu trữ các số và "Không bao giờ sử dụng float" là không đúng - bạn chỉ cần biết các số của mình, ví dụ như các phép đo nhiệt độ sẽ tốt như phao.
@abatishchev và @japongskie: tiền tố phía trước các hàm và procs được lưu trữ SQL vẫn là một ý tưởng hay, nếu không bắt buộc; các liên kết bạn đã đề cập chỉ hướng dẫn không sử dụng tiền tố "sp_" cho các thủ tục được lưu trữ mà bạn không nên sử dụng, các tiền tố khác cũng được, ví dụ "usp_" hoặc "spBob_"
Tham khảo: "Tất cả các số nguyên có 6 chữ số thập phân có nghĩa trở xuống có thể được chuyển đổi thành giá trị dấu phẩy động IEEE 754 mà không làm mất độ chính xác": https://en.wikipedia.org/wiki/Single-pre khít_floating-point_format