簡體   English   中英

SQL str()vs round()函數

[英]SQL str() vs round() function

在使用str()函數時,我發現在某些情況下,round()舍入錯誤,而round()函數按預期工作。 請看一下這個例子:

declare @v decimal(18,2) = 29.95
select str(@v, 18, 1)
--29.9
select round(@v, 1)
--30.00

set @v = 39.95
select str(@v, 18, 1)
--40.00
select round(@v, 1)
--40.00

誰能解釋為什么會這樣?

EDIT1 :我使用以下基本代碼測試了不同的變通方法:

declare @v decimal(18,2) = 9.95
declare @r varchar(100)
declare @c int = 1000000
declare @ms int
declare @dt datetime2

set @dt = sysdatetime()

while @c > 0
begin
    set @r = --different roundings
    set @c = @c - 1
end

set @ms = DATEDIFF(ms, @dt, sysdatetime())
select @ms, @r

選項1(原始的,在某些情況下錯誤地輪回):

str(@v, 18, 1)

選項2(略有修改但正確舍入):

str(round(@v, 1), 18, 1)

選項3(雙轉換和舍入):

convert(varchar(20), convert(decimal(18,1), round(@v, 1)))

選項4(僅雙轉換):

convert(varchar(20), convert(decimal(18,1), @v))

結果 :選項1和2大約比最后兩個慢2倍,但結果是右對齊的。 選項4最快。

str()的參數是一個浮點數,因此您的十進制值會隱式轉換為float(53),然后轉換為字符串。 所以你看到一個浮點舍入錯誤。

對您的查詢稍作修改,您就可以看到實際執行計划中發生了什么。

declare @v decimal(18,2) = 29.95
select top(1) str(@v, 18, 1)
<ScalarOperator ScalarString="str(CONVERT_IMPLICIT(float(53),[@v],0),(18),(1))">

STR()的語法; STR(float_expression [,length [,decimal]])清楚地表明該數字是一個float_expression。 因此,無論您給出的數字是多少,都將首先轉換為FLOAT(n),其中默認值n = 53。

所以

SELECT STR(4.65,5,1),SELECT STR(3.65,5,1)

等於:

SELECT STR(CAST(4.65 AS FLOAT(53)),5,1),STR(CAST(3.65 AS FLOAT(53)),5,1)

如果指定n,比如n = 4,它將給出你期望的答案(即4.7和3.7)

SELECT STR(CAST(4.65 AS FLOAT(4)),5,1),STR(CAST(3.65 AS FLOAT(4)),5,1) - 4.7,7.7

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM