ITPub博客

首页 > 数据库 > PostgreSQL > Unnest函数的几个小特性

Unnest函数的几个小特性

原创 PostgreSQL 作者:u_aa03cac0d7fc 时间:2024-04-06 10:50:45 0 删除 编辑

本文将介绍unnest函数的如下几个小特性:

  • 使用support属性准确预估行
  • 将字符串转化为表
  • 基于ordinality属性生成行号
  • 巧用variadic可变参数

使用support属性准确预估行

PostgreSQL 12对函数新增了support属性,函数使用support属性之后,优化器可以准确的预估行。

PostgreSQL 12及以上的版本,可以看到下面预估的行数是比较准确的。

postgres=# explain select * from unnest(array[1,2,3]);
                        QUERY PLAN                         
-----------------------------------------------------------
 Function Scan on unnest  (cost=0.00..0.03 rows=3 width=4)
(1 row)

我们可以查看函数的定义,PostgreSQL 12里unnest函数增加了support属性。

postgres=# \sf unnest(anyarray)
CREATE OR REPLACE FUNCTION pg_catalog.unnest(anyarray)
 RETURNS SETOF anyelement
 LANGUAGE internal
 IMMUTABLE PARALLEL SAFE STRICT ROWS 100 SUPPORT array_unnest_support
AS $function$array_unnest$function$

将字符串转化为表

下面的示例使用string_to_array函数结合unnest函数将字符串转换为表。

postgres=# select unnest(string_to_array('a,b,c,d',','));
 unnest 
--------
 a
 b
 c
 d
(4 rows)

在PostgreSQL 14及以上的版本,可以使用string_to_table函数进行简化。

postgres=# select string_to_table('a,b,c,d',',');
 string_to_table 
-----------------
 a
 b
 c
 d
(4 rows)

string_to_table()等价于unnest(string_to_array())。

基于ordinality属性生成行号

继续沿用上面的示例,unnest函数后面使用with ordinality属性可以比较方便的生成行号。

postgres=# select f1,f2 from 
            unnest(string_to_array('a,b,c,d',',')) 
            with ordinality t(f2,f1);
 f1 | f2 
----+----
  1 | a
  2 | b
  3 | c
  4 | d
(4 rows)

巧用variadic可变参数

下面的示例,有一张航天工程的表结构如下

create table projects(
project_name varchar primary key, 
spaceman varchar, 
degree varchar
);

构造两条数据:

insert into projects(project_name, spaceman, degree)
values 
('神舟N号',  
'张三
李四
王五', 
'本科
本科
博士'),
('月盾计划',  
'沈腾
马丽', 
'本科
硕士');

打印表数据如下,每行为一次航天工程,第二列包含所有航天员的名称,第三行为航天员对应的学位。

postgres=# select * from projects ;
 project_name | spaceman | degree 
--------------+----------+--------
 神舟N号      | 张三    +| 本科  +
              | 李四    +| 本科  +
              | 王五     | 博士
 月盾计划     | 沈腾    +| 本科  +
              | 马丽     | 硕士
(2 rows)

PostgreSQL里可以非常容易对第二列和第三列进行分解:

postgres=# select p.project_name, e.name, e.degree
             from projects as p,
                  unnest(string_to_array(spaceman, e'\n'),
                         string_to_array(degree, e'\n')) as e(name, degree);
 project_name | name | degree 
--------------+------+--------
 神舟N号      | 张三 | 本科
 神舟N号      | 李四 | 本科
 神舟N号      | 王五 | 博士
 月盾计划     | 沈腾 | 本科
 月盾计划     | 马丽 | 硕士
(5 rows)

保持联系

本人组建了一个技术交流群:PG乐知乐享交流群。欢迎关注文章的小伙伴随缘加入,进群请加本人微信skypkmoon并备注PG乐知乐享。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69978456/viewspace-3011556/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-06-12

  • 博文量
    102
  • 访问量
    50371