暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

Unnest函数的几个小特性

原创 多米爸比 2022-11-26
1483

本文将介绍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)

保持联系

从2019年12月开始写第一篇文章,分享的初心一直在坚持,本人现在组建了一个PG乐知乐享交流群,欢迎关注我文章的小伙伴加我微信进群吹牛唠嗑,交流技术。

456.png

最后修改时间:2022-11-26 19:21:00
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论