0

在过去的 20 年里,我使用过许多数据库,并且只遇到过这种“有趣”类型的 SQL Server 隐式数据转换问题。

如果我创建一个带有一个小的 int 列的表并在其中插入两行值 1 和 2,然后运行以下查询“Select Avg(Column) From table”,我会得到一个截断的结果,而不是我会得到的 1.5来自地球上几乎任何其他 dB 的数据,它们会自动增大数据类型以存储整个结果,而不是截断/舍入到列数据类型。现在我知道我可以为每一种可能的情况解决这个问题,但不是一个好的动态解决方案,特别是对于使用数据分析产品的数据分析...... IE:Cognos/Microstrategy 等......

我在数据仓库中,并且有包含数百万行的事实表......我很想存储小列并获得适当的聚合结果。我目前解决这个细微差别的方法是将最小的可量化列定义为 Numeric(19,5) 以考虑所有情况,即使这些列多次只存储 1 或 0,tinyint 会很好但不会自然聚合出色地。

是否没有任何指令告诉 SQL Server 做所有其他数据库(oracle/db2/informix/access 等)所做的事情?哪个是推广到更大的类型并显示整个结果并让我对它们做我想做的事情?

4

3 回答 3

1

You could create views on the tables which would cast the smallint or tinyint to float and only publish these views to the users. This would keep the small memory usage. The conversion should be no overhead, compared to other database systems that must do that as well if they use a different data type for aggregation.

于 2013-08-27T22:19:13.773 回答
1

据我所知,最快的方法是进行隐式转换:SELECT AVG(Field * 1.0). 您当然可以以同样的方式进行显式强制转换。据我所知,没有办法告诉 SQL Server 在平均整数时您希望将整数转换为浮点数,并且可以说这实际上是正确的行为。

于 2013-09-02T18:05:41.223 回答
1

虽然这可能会让您感到沮丧,但许多编程语言也会以这种方式处理 int,1 / 2会吐出0. 看:

对于 c++ 整数,1 除以 2 是否可靠地等于 0,并且 3/2 = 1、5/2 = 2 等等?

这是一个设计怪癖,如果他们改变它会破坏很多东西。你问你能不能改变一个相当基本的 SQL Server 行为方式,从而可能破坏服务器上运行的任何其他人的代码。

简单地说,不,你不能。

你错了,其他所有数据库产品都以这种方式运行,Derby 也做同样的事情:

http://docs.oracle.com/javadb/10.6.2.1/ref/rrefsqlj32693.html

在 Oracle 文档中,他们特别警告您,无论原始类型如何,AVG 都会返回一个浮点数。这是因为每种语言都必须做出选择,我是返回原始类型还是最精确的答案?为了阻止溢出,许多语言选择了前者,这让各地的程序员不断感到沮丧。

所以在 SQL Server 中,要取出一个浮点数,就放一个浮点数。

于 2013-09-01T10:58:41.373 回答