likes
comments
collection
share

PostgreSQL技术问答26 - Math

作者站长头像
站长
· 阅读数 25

本文是《PostgreSQL技术问答》系列文章中的一篇。关于这个系列的由来,可以参阅开篇文章:

文章的编号只是一个标识,在系列中没有明确的逻辑顺序和意义。读者进行阅读时,不用太关注这个方面。

本文主要讨论的内容是在Postgres中,如何进行相关的数学计算,就是Math相关特性和功能。

Postgres如何实现数学计算

Postgres可以直接在SQL语句中,进行相关字段和数据的数学计算。它们的实现一般有两种方式,操作符和函数。操作符的使用大体和通用的编程语言相同,可以完成最常见和基本的数学计算操作,并且容易理解和使用。对于更复杂和多样的数学计算,Postgres提供了很多内置相关的函数,也可以直接在SQL语句中使用。

在实际使用过程中,可能需要稍微注意一下,操作符和函数一般都有操作数的数据类型的限制,使用时需要进行确认或者转换。当然,在很多情况下Postgres也会帮助使用者自动进行转换,简化操作和使用,具体的问题,需要在具体的场景中进行检查和测试。

从数学类型方面来看,Postgres中提供的方法,大体包括了整数(包括二进制形式)和数字类型(浮点或者双精度)。

有那些可用的数学计算符号

下表列出了在Postgres中,可以直接使用的数学计算操作符:

操作符功能和描述示例结果
+加法操作2 + 35
-减法操作5 - 32
*乘法操作2 * 36
/除法操作7.0 / 23.5
/整数除法操作7 / 23
%求余操作5 % 41
求幂操作2 ^ 38
|/平方根|/ 93
||/立方根||/273
!阶乘5 !120
!!阶乘前缀模式!! 5120
@求绝对值@ -5.05
&比特与91 & 1511
|比特或32 | 35
#比特异或17 # 520
~比特非~ 1-2
<<比特左移位1 << 416
>>比特右移位8 >> 22

合理的使用PG数学计算操作符,可以大大简化SQL语句的编写和功能实现。但这些操作符的使用,有一些学习和理解的门槛,开发者需要平衡使用。实际上,PG提供了可以自定义的操作符和操作计算方式,用户可以自己定义操作符(和已有的不冲突),来完成更复杂的数据计算或者组合。

有那些可用的数学计算函数

PG提供的数学计算相关的函数,主要有三种类型,包括了常规数学计算,三角函数和随机函数等等。下表列出了Postgres支持的数学计算相关的函数:

函数结果数据类型功能和描述示例
abs(x)同输入求绝对值abs(-17.4) -> 17.45
cbrt(dp)dp求立方根cbrt(27.0) -> 3
ceil(dp/n)同输入比当前数更大或相等的整数(天花板)ceil(-42.8) -> -42
ceiling(dp/n)同输入和ceil相同ceiling( 95.3) -> 96
degrees(dp)dp弧度转角度degrees(0.5) -> 28.64788975654126
div(n,n)同输入除法操作,支持整数除法div(9,4) -> 2
exp(dp/n)同输入求自然对数的指数exp(1.0) -> 2.718281828459056
floor(dp/n)同输入比当前更小或相等的整数(地板)floor(-42.8) -> -43
ln(dp/n)同输入求自然对数ln(2.0) -> 0.6931471805599456
log(dp/n)同输入以10为底的对数log(100.0) -> 2
log(n,n)dp求给定底数的对数log(2.0, 64.0) -> 6.0000000000
mod(y, x)同输入除法求余mod(9,4) -> 1
pi()dp"π" 常数值3.14159265358979
power(dp,dp)同输入求幂power(9.0, 3.0)->
radians(dp)dp角度转弧度radians(45.0) -> 0.785398163397448
round(dp/n)同输入近似取整round(42.4) -> 42
round(dp/n, i)n近似保留位数round(42.4382, 2) -> 42.44
sign(dp/n)同输入取符号(-1, 0, +1)sign(-8.4)-> -1
sqrt(dp/n )同输入平方根sqrt(2.0) -> 1.4142135623731
trunc(dp/n)同输入截断取整trunc(42.8) -> 42
trunc(n, i)n截断保留位数trunc(42.4382, 2) -> 42.43
width_bucket(n,n,n,i)i求某值(参数1),落入在将从b1(参数2)到b2(参数3)分隔成为i个桶中的桶的位置width_bucket(5.35, 0.024, 10.06, 5) -> 3
width_bucket(dp,dp,dp,i)i同width_bucket(参数类型差别)
random()n取0和1之间的随机数random() -> 0.132324
setseed(dp)n设置随机数种子
sin(x)dp三角函数sin
cos(x)dp三角函数cos
tan(x)dp三角函数tan
cot(x)dp三角函数cotangent
asin(x)dpsin倒数
acos(x)dpcos倒数
atan(x)dptangent倒数
atan2(y,x)dptangent y/x 的倒数

举几个SQL语句的例子

了解了上述操作符和函数定义之后,可以在SQL语句中作为表达式进行使用,示例如下:

select 1+2, 3-4, 5*6, 7/8;
 ?column? | ?column? | ?column? | ?column? 
----------+----------+----------+----------
        3 |       -1 |       30 |        0
(1 row)

with D(d1,d2) as (values (1.1, -2.1), (-1.8, 3.9) ) select d1, ceil(d1), floor(d1), round(d1) from D;
  d1  | ceil | floor | round 
------+------+-------+-------
  1.1 |    2 |     1 |     1
 -1.8 |   -1 |    -2 |    -2
(2 rows)

Time: 184.648 ms

可以看到,这些数学操作符和函数,和正常的SQL表达式使用是没有什么差异的,非常简单易用。

有什么需要注意的地方吗

笔者认为, 作为一个编程和应用平台,Postgres支持相关数学数值的计算和操作,也是应有之义。但我们应该能够感觉到,如果在SQL中加入了一些比较高级的数学计算(例如求根、三角函数等),当数据量比较大的时候,还是会对性能造成一些影响的。所以,数据库系统的长处在于数据的存储和查询,而非计算。有相关的处理需求,需要仔细的评估和验证,确保这些操作不会对高负荷的数据库应用造成影响。

如果在这方面出现问题,可以考虑两种缓解方案。一是使用外部程序,如在前端进行处理和计算;二是如果数据变更不频繁,可以考虑计算后进行存储,而非查询时计算。

另一个需要注意的地方就是,很多操作符和操作函数的参数,是有数据类型的限制的,在实际使用时,需要注意相关参数的匹配和数据类型的正确转换。

小结

本文讨论了Postgres中,如何支持数学计算的实现方式,包括可用的计算方式,相关的操作符和函数等等。这部分的内容不是很多,概念也比较清晰简单。开发者只需要在合适的场景中,知晓这些功能特性,并且能够按照业务需求灵活应用即可。

转载自:https://juejin.cn/post/7395867506056151094
评论
请登录