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

Pet*_*tch 4 postgresql precision integer casting division

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

与许多编程语言类似,如果两个操作数都是整数,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
Run Code Online (Sandbox Code Playgroud)

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

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

CAST( value AS type )
Run Code Online (Sandbox Code Playgroud)

例如:

CAST( COUNT(DISTINCT(bc.book_id)) AS DOUBLE PRECISION )
Run Code Online (Sandbox Code Playgroud)

它还支持以下语法:

value::type
Run Code Online (Sandbox Code Playgroud)

例如:

COUNT(DISTINCT(bc.book_id))::decimal
Run Code Online (Sandbox Code Playgroud)

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

我的问题是关于要使用的数字类型。

在转换COUNT(DISTINCT(bc.book_id))为非整数类型时,Postgres 提供以下类型:

  • decimal
  • numeric
  • real
  • double precision

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

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

Lau*_*lbe 5

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

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

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

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

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

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

使用CAST语法的优点是符合标准。

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