5

当我执行这个 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 一样吗?

谢谢。

4

5 回答 5

3

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

首先,您的文字表达式的数据类型是什么?我不确定(也没有查)所以我运行了以下命令:

select 1.4 union all
select 'frob'

返回错误:

消息 8114,级别 16,状态 5,第 1
行将数据类型 varchar 转换为数字时出错。

好的,所以1.4和其他文字是numeric- aka decimal

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

十进制(38, s)

好的,所以SUM查询中 3 个表达式的数据类型是decimal(38,1),decimal(38,4)decimal(38,2). 鉴于这 3 种数据类型可供选择,decimal(38,1)最终选择的类型是基于不同精度和比例的规则。

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

所以,最后,回到文档decimal

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

所以这就是你的最终结果。


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

于 2013-11-25T11:40:08.373 回答
0

尝试这个

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

或者

SELECT sum(1.4)/1.0 UNION ALL
SELECT sum(2.0400) union all
SELECT sum(1.24)
于 2013-08-26T10:08:17.983 回答
0

普通查询传递字符串值,否则使用总和或小数将字符串转换为指定格式这是事实

SELECT sum(convert(decimal,1.4,3)) UNION ALL
SELECT sum(2.0400) union all
SELECT sum(1.24)
于 2013-08-26T10:08:21.443 回答
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))
于 2013-08-26T10:06:46.040 回答
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))
于 2013-08-28T03:07:34.810 回答