这是在 SQL 中转换、舍入和平均对象的正确方法吗?
Is this the correct way to cast, round, and avg an object in SQL?
问题
如何使用 avg
和 round
在 PostgreSQL 中提供小数点?
将字符串转换为十进制数需要什么函数?
使用的函数
第一个函数
AVG(ratings.dating) AS scent_avg
第一个错误
Error: expected { scents_id: 1, scent_avg: 4.5 } response body, got { scents_id: 1, scent_avg: '4.5000000000000000' }
第二个函数
ROUND(AVG(ratings.rating), 1) AS scent_avg
第二个错误
Error: expected { scents_id: 1, scent_avg: 4.5 } response body, got { scents_id: 1, scent_avg: '4.5' }
第三个函数
什么函数用于将字符串转换为数字?
编辑
看来我精神失常了。 sticky bit 澄清了 int 没有小数点!我从原来的 post.
中删除了 int 位
在大多数数据库中,这应该可以解决问题:
cast(avg(ratings.ratio * 1.0) as decimal(4, 1))
我在这里没有看到任何四舍五入。 4.5
是 4
和 5
数学上的平均值。
格式化字符串
使用 to_char()
获取没有无用零(或填充空格)的格式化字符串 - 如您评论的那样“四舍五入到小数点后十位”:
SELECT to_char(round(avg(ratings.rating), 10), 'FM999999999990.9999999999')
注意一个 0
。通常你无论如何都想要那个位置。喜欢 0.3
。添加任意数量的 9
允许数字。 The manual:
0
specifies a digit position that will always be printed, even if it
contains a leading/trailing zero. 9
also specifies a digit position,
but if it is a leading zero then it will be replaced by a space, while
if it is a trailing zero and fill mode is specified then it will be deleted.
fill mode (suppress leading zeroes and padding blanks)
没有无关紧要的尾随零的数值
转换为 double precision
(float8
) 以获得不带无关紧要尾随零的数值。演员修剪无关紧要的零。通常,转换为浮点数会引入极端情况舍入错误。
我首先提出了更复杂的解决方案,但由于您只对小数点后十位的精度感兴趣,而 float8
精确到 15 位小数,因此该问题不适用。 The manual:
On all currently supported platforms, the real
type has a range of
around 1E-37 to 1E+37 with a precision of at least 6 decimal digits.
The double precision
type has a range of around 1E-307 to 1E+308 with
a precision of at least 15 digits. Values that are too large or too
small will cause an error. Rounding might take place if the precision
of an input number is too high. Numbers too close to zero that are not
representable as distinct from zero will cause an underflow error.
所以只是:
SELECT round(avg(ratings.rating), 10)::float8
请注意,我们在 舍入后进行 转换,因为 round()
接受小数位的变体仅适用于 numeric
(由于不精确浮点数内部存储的性质)。
在 Postgres 内部,您不必太担心那些尾随零。 The manual:
Numeric values are physically stored without any extra leading or
trailing zeroes. Thus, the declared precision and scale of a column
are maximums, not fixed allocations. (In this sense the numeric type
is more akin to varchar(n)
than to char(n)
.) The actual storage
requirement is two bytes for each group of four decimal digits, plus
three to eight bytes overhead.
参见:
- PostgreSQL adds trailing zeros to numeric
在 Postgres 内部,平等建立正确:
SELECT numeric '4.50000000' = numeric '4.5' -- true
SELECT jsonb '{"scents_id": 4.5}' = jsonb '{"scents_id": 4.5000}' -- true
您的客户端抛出错误似乎是在比较文本表示形式,这是一个微妙的错误。因此,您可能必须像客户期望的那样格式化...
问题
如何使用 avg
和 round
在 PostgreSQL 中提供小数点?
将字符串转换为十进制数需要什么函数?
使用的函数
第一个函数
AVG(ratings.dating) AS scent_avg
第一个错误
Error: expected { scents_id: 1, scent_avg: 4.5 } response body, got { scents_id: 1, scent_avg: '4.5000000000000000' }
第二个函数
ROUND(AVG(ratings.rating), 1) AS scent_avg
第二个错误
Error: expected { scents_id: 1, scent_avg: 4.5 } response body, got { scents_id: 1, scent_avg: '4.5' }
第三个函数
什么函数用于将字符串转换为数字?
编辑
看来我精神失常了。 sticky bit 澄清了 int 没有小数点!我从原来的 post.
中删除了 int 位在大多数数据库中,这应该可以解决问题:
cast(avg(ratings.ratio * 1.0) as decimal(4, 1))
我在这里没有看到任何四舍五入。 4.5
是 4
和 5
数学上的平均值。
格式化字符串
使用 to_char()
获取没有无用零(或填充空格)的格式化字符串 - 如您评论的那样“四舍五入到小数点后十位”:
SELECT to_char(round(avg(ratings.rating), 10), 'FM999999999990.9999999999')
注意一个 0
。通常你无论如何都想要那个位置。喜欢 0.3
。添加任意数量的 9
允许数字。 The manual:
0
specifies a digit position that will always be printed, even if it contains a leading/trailing zero.9
also specifies a digit position, but if it is a leading zero then it will be replaced by a space, while if it is a trailing zero and fill mode is specified then it will be deleted.
fill mode (suppress leading zeroes and padding blanks)
没有无关紧要的尾随零的数值
转换为 double precision
(float8
) 以获得不带无关紧要尾随零的数值。演员修剪无关紧要的零。通常,转换为浮点数会引入极端情况舍入错误。
我首先提出了更复杂的解决方案,但由于您只对小数点后十位的精度感兴趣,而 float8
精确到 15 位小数,因此该问题不适用。 The manual:
On all currently supported platforms, the
real
type has a range of around 1E-37 to 1E+37 with a precision of at least 6 decimal digits. Thedouble precision
type has a range of around 1E-307 to 1E+308 with a precision of at least 15 digits. Values that are too large or too small will cause an error. Rounding might take place if the precision of an input number is too high. Numbers too close to zero that are not representable as distinct from zero will cause an underflow error.
所以只是:
SELECT round(avg(ratings.rating), 10)::float8
请注意,我们在 舍入后进行 转换,因为 round()
接受小数位的变体仅适用于 numeric
(由于不精确浮点数内部存储的性质)。
在 Postgres 内部,您不必太担心那些尾随零。 The manual:
Numeric values are physically stored without any extra leading or trailing zeroes. Thus, the declared precision and scale of a column are maximums, not fixed allocations. (In this sense the numeric type is more akin to
varchar(n)
than tochar(n)
.) The actual storage requirement is two bytes for each group of four decimal digits, plus three to eight bytes overhead.
参见:
- PostgreSQL adds trailing zeros to numeric
在 Postgres 内部,平等建立正确:
SELECT numeric '4.50000000' = numeric '4.5' -- true
SELECT jsonb '{"scents_id": 4.5}' = jsonb '{"scents_id": 4.5000}' -- true
您的客户端抛出错误似乎是在比较文本表示形式,这是一个微妙的错误。因此,您可能必须像客户期望的那样格式化...