↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发中的版本: 19 / 20devel
已结束支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3
预发布版本文档。 PostgreSQL 19beta4 为测试版本,最终发布内容可能有所不同。

F.18. intagg — 整数聚合器和枚举器 #

intagg 模块提供一个整数聚合器和一个枚举器。由于已经有内置函数提供了其能力的超集,所以 intagg 现已过时。不过,该模块仍作为这些内置函数的兼容性包装器提供。

F.18.1. 函数 #

聚合器是聚合函数 int_array_aggregate(integer),它会生成一个整数数组,其中恰好包含输入给它的那些整数。这是对 array_agg 的包装器,后者对任意数组类型都能做同样的事情。

枚举器是函数 int_array_enum(integer[]),它返回 setof integer。本质上,它是聚合器的逆操作:给定一个整数数组,将其展开为一组行。这是对 unnest 的包装器,后者对任意数组类型都能做同样的事情。

F.18.2. 使用示例 #

许多数据库系统都有多对多表这一概念。这样的表通常位于两个带索引的表之间,例如:

CREATE TABLE left_table  (id INT PRIMARY KEY, ...);
CREATE TABLE right_table (id INT PRIMARY KEY, ...);
CREATE TABLE many_to_many(id_left  INT REFERENCES left_table,
                          id_right INT REFERENCES right_table);

它通常按如下方式使用:

SELECT right_table.*
FROM right_table JOIN many_to_many ON (right_table.id = many_to_many.id_right)
WHERE many_to_many.id_left = item;

这将返回左侧表中某个条目在右侧表中对应的所有条目。这是 SQL 中非常常见的一种构造。

但是,如果 many_to_many 表中的条目非常多,这种方法就会变得相当繁琐。通常,对于左侧表中的某个特定条目,右侧表中的每个对应条目都要执行一次索引扫描并取回一行。如果你的系统非常动态,那就没有太多办法。不过,如果有一部分数据相当静态,你可以借助聚合器创建一个汇总表。

CREATE TABLE summary AS
  SELECT id_left, int_array_aggregate(id_right) AS rights
  FROM many_to_many
  GROUP BY id_left;

这样会创建一个表,其中左侧每个条目对应一行,并附带一个由右侧条目组成的数组。不过,如果没有某种使用该数组的方法,它就几乎没有用处;这正是数组枚举器存在的原因。你可以这样做:

SELECT id_left, int_array_enum(rights) FROM summary WHERE id_left = item;

上面这个使用 int_array_enum 的查询,产生的结果与下面的查询相同:

SELECT id_left, id_right FROM many_to_many WHERE id_left = item;

区别在于,针对汇总表的查询只需要从表中取出一行,而直接查询 many_to_many 则必须对每个条目都进行索引扫描并取回一行。

在某个系统上,EXPLAIN 显示,某个查询的代价从 8488 降到了 329。原始查询是一个涉及 many_to_many 表的连接,后来被替换为:

SELECT id_right, count(id_right) FROM
  ( SELECT id_left, int_array_enum(rights) AS id_right
    FROM summary
    JOIN (SELECT id FROM left_table
          WHERE id = item) AS lefts
    ON (summary.id_left = lefts.id)
  ) AS list
  GROUP BY id_right
  ORDER BY count DESC;

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.