-- Transact SQL: case when 1=1 then 0.5 else ceiling(sh) end /* returns 1 (!) why? */
declare @T table (h decimal(2,1))
insert @T (h) values (1.0)
select
case when 1=1 then 0.5 else ceiling(sh) end /* returns 1 (!) why? */
from @T T1
join (select sum(h) as sh from @T )T2 on 1 = 1
答案 0 :(得分:3)
答案与int
数据类型无关
0.5
的数据类型为decimal(1,1)
CEILING
上应用decimal(p,s)
会返回类型为的结果
decimal(p,0)
SUM
上应用decimal(p,s)
会返回以下结果:
输入decimal(38,s)
CASE
表达式
decimal(p1,s1)
或decimal(p2,s2)
的结果将使用与UNION
输入这些数据类型时相同的规则,并具有精度(*
)
max(s1, s2) + max(p1-s1, p2-s2)
的数量和max(s1, s2)
的规模
*
结果的精度和小数位数的绝对最大值为38。 结果精度大于38,则减小为38,并且 缩小相应规模,以防止 被截断的结果。 (source)
因此您的列h
的数据类型为decimal(2,1)
,当应用SUM
时的数据类型为decimal(38,1)
,对其应用的CEILING
的数据类型为{ {1}}。然后在decimal(38,0)
CASE
表达式中使用它
decimal(1,1)
还有
max(s1, s2) + max(p1-s1, p2-s2)
max( 0, 1) + max( 38, 0) = 1 + 38 = 39
因此,所需的结果数据类型将为max(s1, s2) = max(0, 1) = 1
。该值大于38,因此可以得到上述的比例缩减,最后得到decimal(39,1)
-decimal(38,0)
在转换为该数据类型时会四舍五入为0.5
。
如果您希望保留最终结果的精度,则可以使用
1
这样做有一个很小的额外溢出风险,但要使其受到打击,总和必须加起来为以下值之一
case when 1=1 then 0.5 else CAST(ceiling(sh) AS decimal(38,1)) end
9999999999999999999999999999999999999.5
9999999999999999999999999999999999999.6
9999999999999999999999999999999999999.7
9999999999999999999999999999999999999.8
使9999999999999999999999999999999999999.9
本身适合SUM
,但38,1
不适合。
答案 1 :(得分:-3)
当运算符组合两个不同数据类型的表达式时,数据类型优先级规则将优先级较低的数据类型转换为优先级较高的数据类型。如果该转换不是受支持的隐式转换,则返回错误。当两个操作数表达式具有相同的数据类型时,运算结果将具有该数据类型。
在您的情况下,由于优先级较高,因此转换为int
。
declare @T table (h decimal(2,1))
insert @T (h) values (1.0)
select
case when 1=1 then 0.5 else ceiling(sh)*1.0 end -- << convert to float
from @T T1
join (select sum(h) as sh from @T )T2 on 1 = 1