create table #t(序号 int,数量 decimal(18,3),单价 decimal(18,4),币制 varchar(10),总价 decimal(18,2))
insert into #t
select 335 ,0.147, 929.6499, '美元' ,136.66 union all
select 335 ,0.073, 929.6499, '美元', 67.87select * from #t
select
(case when 币制 = '日本元' then ceiling(数量*单价)
else cast(ceiling(数量 * 单价 * 100)/100 as dec(18,2))
end)
from #t where 序号 = 335 select
总价 = (case when 币制 = '日本元' then cast(ceiling(数量 * 单价) as dec(18,2))
else cast(ceiling(数量 * 单价 * 100)/100 as dec(18,2))
end)
from #t where 序号 = 335 想达到的结果是等于日本元的时候保留整数,其他的保留2位置小数,
第二条能显示出想要的结果,第一条语句竟然保留了一位小数,求解自己试验了下,case when 中的then后面和else后面,会统一保留为成最长的小数,但是为什么第一句保存了一位
(case when 币制 = '日本元' then round(数量*单价,0)
else round(数量 * 单价 ,2)
end)
from #t where 序号 = 335
(case when 币制 = '日本元' then cast(ceiling(数量*单价) as dec(18,2))
else ceiling(数量 * 单价 * 100.0)/100
end)
from #t where 序号 = 335
的数据类型是由表达式中具有最高优先级的操作数的数据类型决定的
你的例子中
不管case 表达式哪个为真
结果数据类型均为decimal(具有最高优先级的数据类型)
(case when 币制 = '日本元' then ceiling(数量*单价)
else cast(ceiling(数量 * 单价 * 100)/100 as dec(18,2))
end)
,ceiling(数量*单价)
,数量 * 单价
,ceiling(数量 * 单价 * 100)
,ceiling(数量 * 单价 * 100)/100
,cast(ceiling(数量 * 单价 * 100)/100 as dec(18,2))
from #t where 序号 = 335
结果是
--------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- ---------------------------------------
136.7 137 136.6585353 13666 136.660000 136.66
67.9 68 67.8644427 6787 67.870000 67.87(2 行受影响)
总价 = (case when 币制 = N'日本元' then cast(ceiling(数量 * 单价)as dec(18,2))
else cast(ceiling((数量 * 单价 * 100)/100 )as dec(18,2))
end)
from #t where 序号 = 335 select
总价 = (case when 币制 = '日本元' then cast(ceiling(数量 * 单价) as dec(18,2))
else cast(ceiling(数量 * 单价 * 100)/100 as dec(18,2))
end)
from #t where 序号 = 335
--一个括号改变了结果
原因在于 decimal 类型字段相乘引发的精度问题,sql为防止整数部分被截断,会自动减小小数位
(case when 币制 = '日本元' then ceiling(数量*单价)
else cast(ceiling(数量 * 单价 * 100/100) as dec(18,2))
end)
from #t where 序号 = 335 看下括号的位置
位置不同结果不同
顺便看看我4#的解释
返回的结果应该是 dec(p,s), 其中p=p1+p2+1, s=s1+s2
而当p>38时,就会出现小数位的截断,
据说是以下公式(未验证)
p=p1-s1+s2+max(6,s1+p2+1)
s=max(6,s1+p2+1)而这个例子应该是case when ..then dec(p1,s1) else dec(p2,s2) end中,返回结果的精度问题。返回的结果精度应该是 P = max(p1-s1,p2-s2)+ max(s1,s2) , S=max(s1,s2)
同样当P>38时,S会被截断
这个不是因为“乘”截断,一个ceiling一个cast(dec(18,2))本身就要截断。case when是UNION运算:ceiling(数量*单价): dec(37,0)
cast(dec(18,2)): dec(18,2)dec(37,0) UNION dec(18,2) = dec(38,1)