PostgreSQL|内置函数之GENERATE_SERIES

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
简介: 【7月更文挑战第3天】

【7月更文挑战第3天】

背景

近期在做一些数据处理的工作,工作中使用其他项目组平台来做数据开发,在数据开发过程中,使用了PostgreSQL的一个内置函数 GENERATE_SERIES。在本地测试执行时,并没有什么问题出现,而在项目组开发的平台执行SQL脚本时报错,具体错误提示信息如下:

[ERRORI>> 2024-06-13 09:41:56-执行语句异常【EXECUTE SOL GREENPLUM ERROR{message=ERROR: function generate_series(double precision, double precision, integer) does not exist}

在拿到错误信息时,第一想法就是直接拿着SQL找到数据库管理员,让其协助测试下这个内置函数(GENERATE_SERIES)是否可用。当数据库管理员的发回截图时,我瞬间被懵掉了,这个函数的确存在,而且也可以执行,并有正确的结果输出出来,那么错误的具体原因是什么?为何会出现这个问题呢?下面就开始随我一探究竟吧。

1关于内置函数

对于SQL中的内置函数,应该不会太陌生。所谓内置,就是在安装服务软件后就已存在的函数,它对应的应该是UDF(用户自定义函数)。在SQL中,有许多内置函数(或称为系统函数、内建函数)可用于处理数据。这些函数允许你执行复杂的计算、转换数据类型、处理字符串和日期等。通俗一点讲就是预定义好的功能,用于执行特定任务(也可以说是一个工具类),如处理数据、进行数学运算、处理字符串、日期和时间等。不同的数据库系统(如MySQL、PostgreSQL、SQL Server、Oracle等)可能支持不同的函数集,但许多基本函数在各种系统中都是通用的。

2GENERATE_SERIES

2.1 释义

【函数释义】:数据集函数,按照一定参数规则返回数据集。主要用于生成示例数据或一些有规律的记录,generate_series允许您生成一组从某个点开始,到另一个点结束的数据,并可选择设置递增值。

当前测试(实验)环境为PostgreSQL 16.2,所有操作均以这个版本进行测试(这个后续会有说明)。

2.2 用法

在PostgreSQL的官网有如下三种的用法和描述。

【语法结构】

generate_series ( start integer, stop integer [, step integer ] ) → setof integer

generate_series ( start bigint, stop bigint [, step bigint ] ) → setof bigint

generate_series ( start numeric, stop numeric [, step numeric ] ) → setof numeric

generate_series ( start timestamp, stop timestamp, step interval ) → setof timestamp

generate_series ( start timestamp with time zone, stop timestamp with time zone, step interval [, timezone text ] ) → setof timestamp with time zone

【参数】

从上面的函数结构中,可以看到generate_series这个函数支持三种类型的输入参数,分别为integerbigintnumeric 。如果对这三个函数还没有理解,可以去官网查阅具体的使用方法,或者期待下一篇吧,到时候会详细讲讲。其中,第一个输入参数为开始参数,第二个参数为结束参数,第三个参数(可选,默认不填写时,步长为 1 )为步长。而在返回结果中也是对应到输入参数。

【integer示例】

举例说明下吧,例如我想返回数字 1 到 8 所在范围中步长为1的所有数据(这里可以理解为从1开始计算,在8范围内的所有数据,如果使用N表示数据集,从数学公式上面可以表示为 1 <= N <= 8 或者集合 [1, 8])。当步长为负数时(例如 -2 ),则相反。具体的计算步骤为:

用法一:start <= stop,step =  1时,如果步长为1时,那就是

n1为,start = 1

n2为,n1+1 = 2

n3为,n2+1 = 3

n4为,n3+1 = 4

……

n8为,n7+1 = 8

n9为,n8+1 = 9,此时,结果9>8,不满足在[1,8]集合的范围内,所以舍弃,最终的返回结果如下:

用法二:start <= stop,step =  2时,如果步长为2时,那就是

n1为,start = 1

n2为,n1+2 = 3

n3为,n2+2 = 5

n4为,n3+2 = 7

n5为,n4+2 = 9,此时,结果9>8,不满足在[1,8]集合的范围内,所以舍弃,最终的返回结果如下:

用法三:start >= stop,step = -2时,如果步长为 -2 时(反向获取数据),那就是

n1为,start = 8

n2为,n1+(-2) = 6

n3为,n2+(-2)  = 4

n4为,n3+(-2)  = 2

n5为,n4+(-2)  = 0,此时,结果0<1,不满足在[8,1]集合的范围内,所以舍弃,最终的返回结果如下:

示例中涉及到的代码如下:

select generate_series(1, 8, 1) as N ;
select generate_series(1, 8, 2) as N ;
select generate_series(8, 1, -2) as N ;

2.3 注意

这里需要特别注意下,返回 0 行的情况有如下几个:当步长为正时,如果start大于stop,则返回零行。相反,当步长为负时,如果start小于stop,则返回零行。NULL输入也返回零行。步长不能为 0 。

当 start 大于 stop时,此时开始值为8,加上步长 2 后,为 10,不符合数据集规则,则返回0行。

当 start 小于 stop时,此时开始值为8,加上步长-2 后,为 6,不符合数据集规则,则返回0行。

select generate_series(8, 1, 2) as N ;
select generate_series(1, 8, -2) as N ;

错误根因分析

下面是我写SQL的步骤:

步骤1 套用语法后的原始SQL

select generate_series(2019, 2023, 1) as N;
2019
2020
2021
2022
2023

步骤2 根据业务,获取参数年份前5年的年份数据集,此时想获取的数据集为 2019,2020,2021,2022,2023。

select generate_series('2023' - 4, '2023', 1) as N;
2019
2020
2021
2022
2023

步骤3 我在这里又做了一次画蛇添足,将'2023'转为了 timestamp 类型,最终导致在 PostgreSQL 12版本中无法执行。

在排查根因分析时,错误信息提示我有一个double的参数,可能是哪里写错了,后来才发现是版本的问题。这个错误提示也是让我摸不到头脑。

  • 在PostgreSQL最新开发版本17.x 中

  • 在PostgreSQL 13.x~16.x以及

  • 在PostgreSQL 12.x 以及以前版本中

总结

遇事不要慌,多看看官网,多找找原因,实在不行多翻一翻其他的博文,总有能帮助你的那一刻。下一篇总结下其他参数的使用方法。

[引用]

  1. PostgreSQL 16(generate_series):https://www.postgresql.org/docs/16/functions-srf.html
  2. PostgreSQL 12(generate_series):https://www.postgresql.org/docs/12/functions-srf.html
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
6天前
|
SQL 自然语言处理 关系型数据库
在 PostgreSQL 中使用 `REPLACE` 函数
【8月更文挑战第8天】
56 9
在 PostgreSQL 中使用 `REPLACE` 函数
|
1月前
|
关系型数据库 BI 数据处理
|
2月前
|
JSON 关系型数据库 数据库
PostgreSQL中json_to_record函数的神秘面纱
`json_to_record`是PostgreSQL中的函数,用于将JSON数据转换为RECORD类型,便于查询和分析。基本用法是传入JSON数据,如`SELECT json_to_record(&#39;{&quot;name&quot;: &quot;张三&quot;, &quot;age&quot;: 30}&#39;::json);`。还可结合FUNCTION创建自定义函数,实现复杂功能。在实际应用中,它简化了对JSON格式数据的处理,例如筛选年龄大于30的用户。了解并善用此函数能提升数据库操作效率。本文由木头左分享,期待你的点赞和收藏,下次见!
PostgreSQL中json_to_record函数的神秘面纱
|
2月前
|
SQL 关系型数据库 数据库
PostgreSQL 常用函数分享
PostgreSQL 常用函数分享
19 0
|
3月前
|
SQL 关系型数据库 分布式数据库
在PolarDB for PostgreSQL中,你可以使用LIKE运算符来实现类似的查询功能,而不是使用IF函数
在PolarDB for PostgreSQL中,你可以使用LIKE运算符来实现类似的查询功能,而不是使用IF函数
70 7
|
3月前
|
关系型数据库 PostgreSQL
postgresql日程排程函数的编写实例
postgresql日程排程函数的编写实例
|
3月前
|
SQL 关系型数据库 C语言
PostgreSQL【应用 03】Docker部署的PostgreSQL扩展SQL之C语言函数(编写、编译、载入)计算向量余弦距离实例分享
PostgreSQL【应用 03】Docker部署的PostgreSQL扩展SQL之C语言函数(编写、编译、载入)计算向量余弦距离实例分享
70 0
|
3月前
|
SQL 关系型数据库 数据库
PostgreSQL【应用 02】扩展SQL之C语言函数(编写、编译、载入)实例分享
PostgreSQL【应用 02】扩展SQL之C语言函数(编写、编译、载入)实例分享
106 0
|
关系型数据库 分布式数据库 PolarDB
《阿里云产品手册2022-2023 版》——PolarDB for PostgreSQL
《阿里云产品手册2022-2023 版》——PolarDB for PostgreSQL
332 0
|
存储 缓存 关系型数据库

相关产品

  • 云原生数据库 PolarDB
  • 下一篇
    云函数