PostgreSQL:在将整数转换为非整数类型以强制在 PostgreSQL 中进行浮点除法时,我应该使用哪种数字类型?

PostgreSQL: When casting an integer to a non-integer type to force floating point division in PostgreSQL, which number type should I use?

我知道 Whosebug 上有很多整数除法题,但是我没有看到这个。

与许多编程语言类似,如果两个操作数都是整数,PostgreSQL 会执行整数除法。

如果有:

SELECT s.id AS student_id,
       COUNT(DISTINCT(bc.book_id)) / COUNT(c.id) AS average_books_per_class
FROM student s
     LEFT JOIN class c
        ON c.student_id = s.id
     LEFT JOIN book_class bc
        ON bc.class_id = c.id
GROUP BY s.id

然后为了得到想要的结果,必须将 COUNT(DISTINCT(bc.book_id)) 转换为非整数类型。如果不这样做,那么类似于许多编程语言的 Postgres 会进行整数除法,这不太可能给出人们想要的结果。

Postgres 支持两种语法来执行此转换:

CAST( value AS type )

例如:

CAST( COUNT(DISTINCT(bc.book_id)) AS DOUBLE PRECISION )

它还支持语法:

value::type

例如:

COUNT(DISTINCT(bc.book_id))::decimal

两种语法都有效,我个人更喜欢使用 CAST 的语法,因为它更明确(我认为明确的很好)。其他人可能更喜欢 value::type,因为它既富有表现力又简洁——通常越短(在一定程度上)越好。

我的问题是关于要使用的号码类型。

在将 COUNT(DISTINCT(bc.book_id)) 转换为非整数类型时,Postgres 给出了以下类型:

在我的查询中我选择了DOUBLE PRECISION

我想知道,特别是在除法的情况下,以及在可能需要将 PostgreSQL 中的整数类型转换为非整数类型的任何其他情况下,四种选择中哪一种是最好的一,为什么?

decimalnumeric是同义词,少了一个选择

如果您需要非常高的精度(使用不带任何类型修饰符的 numeric)或者如果您希望四舍五入到一定数量的小数(使用 numeric(20,2)两位小数)。

这种数据类型是精确的,但速度慢,因为它是一种“二进制编码的十进制”类型。

realdouble precision 是 4 字节和 8 字节的浮点数,速度快但有舍入误差和精度有限。

永远不要使用real,它的精度很低。

在大多数实际应用中,为特定目的使用剩余两种类型中的哪一种并不重要。

使用CAST语法的好处是符合标准。

备注:DISTINCT(col)在语法上是正确的,但会误导,因为它不是一个函数。改为写 DISTINCT col