likes
comments
collection
share

PostgreSQL技术问答07 generate_series

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

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

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

本文主要讨论的内容是generate_series,即生成序列。

什么是generate_series(GS)

generate_series(以下简称GS)是PostgreSQL提供的一个内置的函数,可以用在SQL语句中,生成一个数字或时间序列的记录集。

GS如何使用

作为一个函数,GS的标准范式是: generate_series(start, stop, step),这里面的参数分别是序列开始值,序列结束值和步长值。这个形式有点像编程语言中的for循环,即 i= start;i<=stop;i+=step 的样式。如果是整数序列,则step可以省略,默认为1。这个方法的结果是一个只有一个字段的记录集,记录集的行数就是条件循环的次数,内容就是各个循环计算的结果值。

当然,在PG中,GS的用法可以很丰富,下面总结了几种不同的用法,要特别注意参数对结果的影响:

// 最普通的用法
select generate_series(1,5);
 generate_series 
-----------------
               1
               2
               3
               4
               5
(5 rows)

// 使用步长
 select generate_series(1,5,2);
 generate_series 
-----------------
               1
               3
               5
(3 rows)

// 浮点数使用步长
select generate_series(1.5,7.5,2) vl;
 vl  
-----
 1.5
 3.5
 5.5
 7.5
(4 rows)

// 作为子查询或者记录集
select n, n^2 nn from generate_series(1,5) n;
 n | nn 
---+----
 1 |  1
 2 |  4
 3 |  9
 4 | 16
 5 | 25
(5 rows)

select sum(n)  from generate_series(1,101) n;
 sum  
------
 5151
(1 row)

// 日期序列
SELECT * FROM generate_series('2022-01-01'::date, '2022-01-05'::date, '1 day'::interval);
    generate_series     
------------------------
 2022-01-01 00:00:00+00
 2022-01-02 00:00:00+00
 2022-01-03 00:00:00+00
 2022-01-04 00:00:00+00
 2022-01-05 00:00:00+00
(5 rows)

从上面的示例,我们可以总结出一些要点:

  • 各个参数使用的值,不限于整数,也可以使用浮点数,甚至支持日期类型
  • 在使用数值类型时,步长参数可以省略,默认为1
  • 步长可以为负数,用于倒序序列
  • 支持时间序列,但必须指定步长
  • 这个函数执行结果是一个记录集,只有一个字段,默认名称为generate_series,当然,可以重新命名字段名称
  • 序列结束的判断逻辑是 <= stop
  • 可以在select子句或者from子句中使用,即作为子查询使用

有那些使用场景

合理使用GS,可以构造出很多有趣的场景,有些情况下可以大幅度的降低开发的复杂性。GS的在应用开发中使用场景包括但不限于:

  • 快速生成测试数据集

利用GS,可以快速生成大量的数据(如百万级),用于填充测试用的业务数据和信息表。

  • 快速生成大量随机数据

使用GS,结合随机函数如random()或者random_noraml(),就可以生成大量随机数据。

  • 生成编码序列

结合相关的字符串操作,可以利用GS生成一个规则化的编码序列。

select 'ULSC-' || LPAD(ss::text,4,'0') from generate_series(20,60) ss ;

  • 作为循环用的基础记录集

这里就涉及一种认识方式,就是GS不仅可以作为一个数值序列,本质上它其实是一种循环模式。这样就可以作为一种循环操作的数据基础。

  • 快速复制数据

如果想对数据表中的记录快速进行复制,可以使用生成序列,然后对原始数据进行关联查询,但不指定关联条件,就生成了一个序列记录集和原始数据记录集的笛卡尔积的记录集,即将原始数据复制了多个。

  • 生成时间序列

可以以指定的开始时间和间隔,生成一个时间序列,并进行相关的业务操作。例如进行时间周期内的统计分析等等。

如果同时使用多个序列,会发生什么

纯属好奇哈,测试一下就知道了,不知道这里是什么逻辑。

 select generate_series(1,4) m, generate_series(5,10) n;
 m | n  
---+----
 1 |  5
 2 |  6
 3 |  7
 4 |  8
   |  9
   | 10
(6 rows)

// 在看看这个呢?
select generate_series(1,4)*n m from generate_series(5,10) n ;

select generate_series(1,4) * generate_series(10,5);

小结

本文探讨了总结了PostgreSQL中的生成序列(generate_series)技术,讨论了其基本概念,一般形式,应用方式,应用中需要注意的问题,应用的场景等等相关内容。

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