MSSQL - 使用不同的小数精度联合所有

时间:2013-08-26 09:28:16

标签: sql sql-server decimal precision union-all

当我执行这个SQL

SELECT 1.4 UNION ALL
SELECT 2.0400 union all
SELECT 1.24

我得到以下结果:

1.4000
2.0400
1.2400

但是当我执行以下SQL

SELECT sum(1.4) UNION ALL
SELECT sum(2.0400) union all
SELECT sum(1.24)

我得到以下结果:

1.4
2.0
1.2

为什么所有记录的精确度(比例)都有差异? 它不应该总是使用没有数据丢失的精度,就像第一个sql一样吗?

THX。

5 个答案:

答案 0 :(得分:3)

我知道这是一个很老的问题,但现有的答案似乎都没有解决“为什么?”问题的一个方面。

首先,文字表达式的数据类型是什么?我不确定(并且没有查找)所以我运行了以下内容:

select 1.4 union all
select 'frob'

返回错误:

  

Msg 8114,Level 16,State 5,Line 1
  将数据类型varchar转换为数字时出错。

好的,1.4和其他文字是numeric - a.k.a decimal

接下来,如果传递decimal(p,s) 1 SUM函数的返回类型是什么:

  

十进制(38,s)

好的,您的查询中3个SUM表达式的数据类型为decimal(38,1)decimal(38,4)decimal(38,2)。鉴于可供选择的3种数据类型,decimal(38,1)是最终选择的类型,基于differing precisions and scales的规则。

  

结果精度和标度的绝对最大值为38.当结果精度大于38时,相应的标度会减小,以防止结果的整数部分被截断。

最后,回到decimal上的文档:

  

默认情况下,SQL Server在将数字转换为具有较低精度和比例的小数或数值时使用舍入。但是,如果SET ARITHABORT选项为ON,则SQL Server会在发生溢出时引发错误。仅精度和比例的损失不足以引起错误。

这是你的最终结果。


1 起初这种类型可能看起来很令人惊讶,直到你意识到,sum通常会对多行进行操作,并且很容易使给定精度和比例的多个值溢出他们自己的数据类型。对于特定 decimal(38,s)出现,SUM()为最大可能空间提供容量而不会丢失任何精度,并且意味着可以在查询之前确定最终数据类型已经执行了。

答案 1 :(得分:0)

尝试相同的结果,

SELECT Cast(Sum(1.4) As Numeric(18,4)) UNION ALL
SELECT Cast(Sum(2.0400) As Numeric(18,4)) union all
SELECT Cast(Sum(1.24) As Numeric(18,4))

答案 2 :(得分:0)

试试这个

SELECT sum(1.4)/1.0 UNION ALL
SELECT sum(2.0400)/1.0 union all
SELECT sum(1.24)/1.0

OR

SELECT sum(1.4)/1.0 UNION ALL
SELECT sum(2.0400) union all
SELECT sum(1.24)

答案 3 :(得分:0)

普通查询传递字符串值否则使用sum或decimal它是字符串转换为指定格式这是事实

SELECT sum(convert(decimal,1.4,3)) UNION ALL
SELECT sum(2.0400) union all
SELECT sum(1.24)

答案 4 :(得分:0)

尝试此查询

SELECT convert(decimal(18,4),Sum(1.4)) UNION ALL

SELECT convert(decimal(18,4),Sum(2.0400)) UNION ALL

SELECT convert(decimal(18,4),Sum(1.24))